go1.18泛型全部教程
1. 声明一个泛型函数
package main
import "fmt"
func printslice[T any](s []T){
for _,v := range s{
fmt.Printf("%v\n",v)
}
}
func main(){
printslice[int]([]int{66,77,88,99,100})
printslice[float64]([]float64{1.1,2.2,5.5})
printslice[string]([]string{"烤鸡","烤鸭","烤鱼","烤面筋"})
//省略显示类型
printslice([]int64{55,44,33,22,11})
}
[T any]参数的类型,意思是该函数支持任何T类型;
多个泛型参数语法:
[T, M any]
[T any, M any]
[T any, M comparable]
在调用这个泛型函数的时候,可以显示指定类型参数,
如: printslice[int](int
也可以省略显示类型
比如 printslice([]int64(55,44,33,22,11))
2. 声明一个泛型切片
带有类型参数的类型被叫做泛型类型。下面定义一个底层类型为切片类型的新类型 vector。它是可以存储任何类型的的切片。要使用泛型类型,要先对其进行实例化,就是给类型参数指定一个实参。
package main
import "fmt"
type vector[T any][]T
func printslice[T any](s []T){
for _,v := range s{
fmt.Printf("%v",v)
}
}
func main(){
v:=vector[int]{58,1881}
printslice(v)
v2:=vector[string]{"烤鸡","烤鸭","烤鱼","烤面筋"}
printslice(v2)
}
3. 声明一个泛型map
package main
import "fmt"
type M[K string, V any] map[K]V //这里的K不支持any ,由于底层map不支持,所以使用string
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)
}
4. 声明一个泛型通道
package main
import "fmt"
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)
}
5. 泛型约束
使用interface中规定的类型约束泛型函数的参数
package main
import "fmt"
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
}
func add[T NumStr](a,b T) T {
return a + b
}
func main(){
fmt.Println(add(3,4))
fmt.Println(add("hello","world"))
}
上面的 NumStr,新增了类型列表表达式,它是对类型参数进行约束。
使用 | 表示取并集
如果传入参数不在集合限制范围内,就会报错。
使用interface中规定的方法来约束泛型的参数
package main
import (
"fmt"
"strconv"
)
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
~int | ~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中规定的方法和类型来双重约束泛型的参数
package main
import (
"fmt"
"strconv"
)
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约束,判断比较
package main
import (
"fmt"
)
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{"烤鸡", "烤鸭", "烤鱼", "烤面筋"}, "烤面筋"))
}
comparable 的约束类型支持整数 和字符,自定义结构体,也可以嵌套在自定义约束中
type ShowPrice interface {
int | string | comparable
}