Go 泛型使用
Posted by 渐行渐远 on Sunday, March 20, 2022 共757字泛型如何使用
函数 String
声明的参数列表中, str
类型被定义为泛型。支持泛型后,函数的签名中多出来 [T any]
部分,其中,any
表示泛型约束。在调用String
函数时,也明确的指定了泛型类型为字符串。如果我们指定别的类型(和实际传入的类型不一致),编译会出错。
//例子1
func String[T any](str ...T) {
fmt.Println(str)
}
func main() {
String[string]("hello", "world!")
}
虽然 str
被声明为了泛型,但fmt.Println
可以正常打印输出。在 Go 的内建类型了,也新增了any
和comparable
类型。
|
|
函数max
用于判断最大的入参,泛型约束指定为一个类型集合,实际类型是这三个类型中的任意一个。参考上面的例子,用any
来替换这三种类型可以吗?不可以,因为编译器无法判断类型 T 能否进行比较。
//例子2
func max[T int64|float64|int32](a T, b T) T {
if a > b {
return a
}
return b
}
func main() {
m := max[int64](1, 2)
fmt.Print(m)
}
参考上述102行的comparable
类型,泛型约束指定为comparable
可以吗?不可以,comparable
只能被用来比较是否相等,只有是 == 号的情况,才可以。我理解,它主要是用来给map
使用的。
int64|float64|int32
这种声明方式不够简洁,可以通过声明新的类型来简化,优化一下上面的例子2,重新声明了一个Number
类型来表示这个泛型。
type Number interface {
int64 | float64 | int32
}
func max[T Number](a T, b T) T {
if a == b {
return a
}
return b
}
例子3,我们在结构体上声明泛型,看起来可能比较吓人,但实际上并没有特别的新内涵,只是阐述将结构体中的字段声明为泛型的写法。
//例子3
type Live[K comparable, V any, V1 any] struct {
Cache map[K]V
Model V1
}
func (l *Live[K, V, V1]) Set(identity K, content V, model V1) {
l.Cache[identity] = content
l.Model = model
}
func (l *Live[K, V, V1]) Get(identity K) V {
return l.Cache[identity]
}
type Key struct {Title string}
type Value struct {Title string}
func main() {
live := &Live[Key, Value, string]{
Cache: make(map[Key]Value),
}
live.Set(Key{Title: "key"}, Value{Title: "value"}, "")
fmt.Println(live.Get(Key{Title: "key"}))
}