W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
在Go 1.18以前,Go只支持內置泛型。 從Go 1.18開始,Go也支持自定義泛型。 本文只介紹內置泛型。
Go通過各種一等公民組合類型來實現(xiàn)內置泛型。 我們可以用各種一等公民組合類型來組合出無窮個類型。 本文將展示一些自定義組合類型的例子并解釋如何解讀這些自定義類型。
Go中的組合類型字面表示設計得非常直觀和易于解讀。 即使對于一些非常復雜的類型,我們也幾乎不可能在解讀它們的字面形式中迷失。 下面將從簡單到復雜列出一些自定義組合類型的例子并進行解讀。
先看一個簡單的例子:
[3][4]int
當解讀一個類型的字面形式時,我們應該從左到右進行解讀。 左邊開頭的[3]
表示著這個類型為一個數(shù)組類型,它右邊的整個部分為它的元素類型。 對于這個例子,它的元素類型為另外一個數(shù)組類型[4]int
。 此另外一個數(shù)組類型的元素類型為內置類型int
。 第一個數(shù)組類型可以被看作是一個二維數(shù)組類型。
一個使用此數(shù)組類型的例子:
package main
import (
"fmt"
)
func main() {
matrix := [3][4]int{
{1, 0, 0, 1},
{0, 1, 0, 1},
{0, 0, 1, 1},
}
matrix[1][1] = 3
a := matrix[1] // 變量a的類型為[4]int
fmt.Println(a) // [0 3 0 1]
}
類似的,
[][]string
是一個元素類型為另一個切片類型[]string
的切片類型。
**bool
是一個基類型為另一個指針類型*bool
的指針類型。
chan chan int
是一個元素類型為另一個通道類型的chan int
的通道類型。
map[int]map[int]string
是一個元素類型為另一個映射類型map[int]string
的映射類型。
這兩個映射類型的鍵值類型均為內置類型int
。
func(int32) func(int32)
是一個只有一個輸入參數(shù)和一個返回值的函數(shù)類型,此返回值的類型為一個只有一個輸入參數(shù)的函數(shù)類型。
這兩個函數(shù)類型的輸入參數(shù)的類型均為內置類型int32
。
下面是另一個自定義組合類型:
chan *[16]byte
最左邊的chan
關鍵字表明此類型是一個通道類型。 chan
關鍵字右邊的整個部分*[16]byte
表示此通道類型的元素類型,此元素類型是一個指針類型。 此指針類型的基類型為*
右邊的整個部分:[16]byte
,此基類型為一個數(shù)組類型。 此數(shù)組類型的元素類型為內置類型byte
。
一個使用此通道類型的例子:
package main
import (
"fmt"
"time"
"crypto/rand"
)
func main() {
c := make(chan *[16]byte)
go func() {
// 使用兩個數(shù)組以避免數(shù)據(jù)競爭。
var dataA, dataB = new([16]byte), new([16]byte)
for {
_, err := rand.Read(dataA[:])
if err != nil {
close(c)
} else {
c <- dataA
dataA, dataB = dataB, dataA
}
}
}()
for data := range c {
fmt.Println((*data)[:])
time.Sleep(time.Second / 2)
}
}
類似的,類型map[string][]func(int) int
為一個映射類型。 此映射類型的鍵值類型為內置類型string
,右邊剩余的部分為此映射類型的元素類型。 []
表明此映射的元素類型為一個切片類型,此切片類型的元素類型為一個函數(shù)類型func(int) int
。
一個使用了此映射類型的例子:
package main
import "fmt"
func main() {
addone := func(x int) int {return x + 1}
square := func(x int) int {return x * x}
double := func(x int) int {return x + x}
transforms := map[string][]func(int) int {
"inc,inc,inc": {addone, addone, addone},
"sqr,inc,dbl": {square, addone, double},
"dbl,sqr,sqr": {double, double, square},
}
for _, n := range []int{2, 3, 5, 7} {
fmt.Println(">>>", n)
for name, transfers := range transforms {
result := n
for _, xfer := range transfers {
result = xfer(result)
}
fmt.Printf(" %v: %v \n", name, result)
}
}
}
下面是一個看上去有些復雜的類型:
[]map[struct {
a int
b struct {
x string
y bool
}
}]interface {
Build([]byte, struct {x string; y bool}) error
Update(dt float64)
Destroy()
}
讓我們從左到右解讀此類型。 最左邊開始的[]
表明這是一個切片類型,緊跟著的map
關鍵字表明此切片類型的元素為一個映射類型。 map
關鍵字后緊跟的一對方括號[]
中的結構體類型字面形式表明此映射的鍵值類型為一個結構體類型。 此中括號右邊的整個部分表明此映射的元素類型為一個接口類型。此接口類型指定了三個方法。 此映射的鍵值結構體類型有兩個字段,第一個字段的名稱和類型為a
和內置類型int
; 第二個字段的名稱為b
,它的類型為另外一個結構體類型struct {x string; y bool}
。 此另外一個結構體類型也有兩個字段:內置string
類型的字段x
和內置bool
類型的字段y
。
請注意第二個結構體類型也被用做剛提及的接口類型所指定的其中一個方法中的其中一個參數(shù)類型。
我們經常將復雜類型的各個組成部分單獨提前聲明為一個類型名,從而獲得更高的可讀性。 下面的代碼中的類型別名T
和上面剛解讀的類型表示同一個類型。
type B = struct {
x string
y bool
}
type K = struct {
a int
b B
}
type E = interface {
Build([]byte, B) error
Update(dt float64)
Destroy()
}
type T = []map[K]E
Go中當前的內置泛型除了上述類型組合,還有一些支持泛型的內置函數(shù)。 比如,內置函數(shù)len
可以用來獲取各種容器值的長度。 unsafe
標準庫包中的函數(shù)也可以被看作是支持泛型的內置函數(shù)。 這些函數(shù)在前面的各篇文章中已經一一介紹過了。
從1.18版本開始,Go已經支持自定義泛型。 請閱讀《Go自定義泛型101》一書來了解如何使用自定義泛型。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: