在定义函数(结构等)时候,可能会有多种类型传入。只有在真正使用才知道是什么类型,此时就可以用一个更加宽泛的类型(必须存在一定约束,只能在那些类型的范围内使用)暂时占位。这个类型就叫泛型
写法:[泛型标识 泛型约束] ([T int | float64 | string])
使用any约束,实现一个简单的函数
//官网文档解释:any是接口{}的别名,在所有方面等价于接口{},可以匹配所有类型
func same[T any](a, b T) bool {
return a == b
}
func main() {
fmt.Println(same(1, 1)) //true
fmt.Println(same(1.1, 2.1)) //false
fmt.Println(same("1", "10")) //false
}
使用 comparable 约束类型。 comparable 是一个编译器内置的特定的扩展接口类型,该类型必须支持“==“ 方法。
//官方文档:comparable是由所有可比类型实现的接口(布尔值、数字、字符串、指针、通道、
//可比类型数组、结构的字段都是可比较的类型)。可比接口只能用作类型参数约束,不是变量的类型。
func Sum[K comparable, V int | float64](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
func main() {
ints := map[string]int{
"first": 34,
"second": 12,
}
floats := map[string]float64{
"first": 35.98,
"second": 26.99,
}
//Ints=46 Floats=62.97
fmt.Printf("Ints=%v Floats=%v\n", Sum(ints), Sum(floats))
}
//泛型方法 在方法调用的时候去判断是泛型约束(int|float64|string)里的哪一种
func same[T int | float64 | string](a, b T) bool {
return a == b
}
func main() {
//隐式声明 自动转为 same[int](1, 1)
fmt.Println(same(1, 1)) //true
fmt.Println(same[int](1, 1)) //显式声明 true
fmt.Println(same(1.1, 2.1)) //false
fmt.Println(same("1", "10")) //false
}
//泛型结构体 结构体声明的就要定义类型 [T any]表示所以类型都接收
type Person[T any] struct {
Name string
Sex T
}
func main() {
// Person{
// Name string
// Sex string
// }
var p = Person[string]{}
p.Name = "linzhonyi"
p.Sex = "男"
fmt.Println(p)
}
//泛型map 在TMap创建的时候就要定义K,V的类型
type TMap[K int | string, V int | string] map[K]V
func main() {
//make(map[string]string)
m1 := make(TMap[string, string])
m1["a"] = "a"
//make(map[int]string)
m2 := make(TMap[int, string])
m2[1] = "a"
}
type TSlice[T any] []T
func main() {
s := make(TSlice[int], 6)
s[4] = 123
fmt.Println(s)
}
七、创建泛型约束
//创建泛型约束接口
type MyType interface {
int | float64 | string | bool | int64
}
func test[T MyType](t T) {
fmt.Println(t)
}
func main() {
test(111) //111
test("222") //222
test(3.33) //3.33
test(true) //true
}
当定义了自定义类型时正常的泛型接口是无法识别的,需要在泛型接口的类型前加~,表示涵盖底层类型.
//创建泛型约束接口
type MyType interface {
~int | ~float64
}
//自定义类型
type MyInt int
type MyFloat float64
func test[T MyType](t T) {
fmt.Println(t)
}
func main() {
mi := MyInt(111)
test(mi) //111
mf := MyFloat(1.11)
test(mf) //1.11
}