Go 泛型

泛型符号

  • any - 空接口,表示任意类型
  • ~T - 表示所有底层类型为T的类型集合,例如: type myInt int 中myInt的底层类型就是int
  • comparable - 指代可以使用==或!=来进行比较的类型集合。可以满足map类型的key的类型要求

声明一个泛型函数

  • 使用 [T any] 来表示该函数支持任何T类型
  • 可以存在不同类型的多个泛型
    • [M, N any]
    • [M any, N any]
    • [M any, N comparable]
  • 调用泛型函数时,可以指定类型,也可以忽略
    • funcName[int](5)
    • funcName(5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 泛型函数
func printAny[T any](s []T){
for _,v := range s{
fmt.Printf("%v\n",v)
}
}

func main(){
printAny[int]([]int{66,77,88,99,100})
printAny[float64]([]float64{1.1,2.2,5.5})
printAny[string]([]string{"aa","bb","cc","dd"})

// 省略显示类型
printAny([]int64{55,44,33,22,11})
}

泛型切片

1
2
3
4
5
6
7
8
type vector[T any] []T

func main(){
v:=vector[int]{1, 2, 3, 4, 5}
fmt.println(v)
v2:=vector[string]{"aa","bb","cc","dd"}
fmt.println(v2)
}

泛型map

1
2
3
4
5
6
7
8
9
type M[K comparable, V any] map[K]V
func main() {
m1 := M[string, int]{"key": 1}
m1["key"] = 2

m2 := M[string, string]{"key": "value"}
m2["key"] = "new value"
fmt.Println(m1, m2)
}

泛型通道

1
2
3
4
5
6
7
8
9
10
11
12
13
type C[T any] chan T

func main() {
c1 := make(C[int], 10)
c1 <- 1
c1 <- 2

c2 := make(C[string], 10)
c2 <- "hello"
c2 <- "world"

fmt.Println(<-c1, <-c2)
}

泛型约束

使用interface规定的类型约束泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 定义的NumStr约束了类型只能为数字和字符串
type NumStr interface {
Num | Str
}
type Num interface {
~int | ~int8 | ~int16| ~int32| ~int64| ~uint| ~ uint8| ~ uint16| ~ uint32| ~uint64| ~ uintptr| ~ float32| ~ float64| ~ complex64| ~ complex128
}
type Str interface {
string
}

// 此处的T只能为数字和字符串类型
func add[T NumStr](a,b T) T {
return a + b
}

func main(){
fmt.Println(add(3,4))
fmt.Println(add("hello","world"))
}

使用interface规定的方法约束泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type Price int

func (i Price) String() string {
return strconv.Itoa(int(i))
}

type Price2 string

func (i Price2) String() string {
return string(i)
}

type ShowPrice interface {
String() string
}

func ShowPriceList[T ShowPrice](s []T) (ret []string) {
for _, v := range s {
ret = append(ret, v.String())
}
return
}

func main() {
fmt.Println(ShowPriceList([]Price{1, 2}))
fmt.Println(ShowPriceList([]Price2{"a", "b"}))
}

使用interface规定的方法和类型约束泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Price int

type ShowPrice interface {
String() string
~int | ~string
}

func (i Price) String() string {
return strconv.Itoa(int(i))
}

func ShowPriceList[T ShowPrice](s []T) (ret []string) {
for _, v := range s {
ret = append(ret, v.String())
}
return
}

func main() {
fmt.Println(ShowPriceList([]Price{1, 2}))
}

使用自带的comparable约束

1
2
3
4
5
6
7
8
9
10
11
12
13
func findFunc[T comparable](a []T, v T) int {
for i, e := range a {
if e == v {
return i
}
}
return -1
}

func main() {
fmt.Println(findFunc([]int{1, 2, 3, 4, 5, 6}, 5))
fmt.Println(findFunc([]string{"aa", "bb", "cc", "dd"}, "dd"))
}

comparable 也可以在自定义结构体中进行约束类型

1
2
3
type MyType interface {
int | string | comparable
}