2022年3月15日,争议非常大但同时也备受期待的泛型终于伴随着Go1.18
发布了。
Go 是一种静态类型编程语言,这意味着在编译时会检查变量和参数的类型。内置类型(map、slice、channel)和内置函数(如 len、cap 或 make)能够接收和返回不同具体类型的值,但在 Go 1.18 之前,用户定义的 Go 类型和函数不能如此。
go version >= 1.18
例如
// 比较int类型
func compareMaxInt(a, b int) int {
if a > b {
return a
}
return b
}
// 比较float64类型
func compareMaxFloat(a, b float64) float64 {
if a > b {
return a
}
return b
}
// 比较int或float64类型
func compareMax[T int | float64](a, b T) T{
if a > b {
return a
}
return b
}
只需要在函数名后面使用中括号[]
声明泛型名称,以及泛型允许出现的类型
// 定义泛型函数
func compareMax[T int | float64](a, b T) T{
if a > b {
return a
}
return b
}
//调用
func main() {
// 自动类型推导
compareMax(10, 20)
// 指定类型
compareMax[float64](10, 20)
}
用于泛型类型过多,或者该泛型类型在多处使用,定义方法类似于接口
// Num 自定义泛型类
type Num interface {
int | float64 | float32 | rune
}
func compare[B Num](a, b B) B {
if a > b {
return a
}
return b
}
any: 表示go里面所有的内置基本类型,等价于interface{}
comparable: 表示go里面所有内置的可比较类型:int、uint、float、bool、struct、指针
等一切可以比较的类型,只可以使用==
和!=
进行比较
func equal(a, b comparable) bool {
return a == b
}
package main
import "fmt"
type Student[K string | []byte, V int | float64] struct {
id int
name K
score V
}
func main() {
s1 := Student[string, int]{1, "lucy", 18}
s2 := Student[[]byte, float64]{1, []byte("lucy"), 18.5}
fmt.Println(s1, s2)
}
为了支持新定义的类型对其底层类型符合的方便使用,golang增加了新的~
字符,意思是如果底层类型int,就可以正常进行泛型的实例化。
package main
type Num interface {
int | float64
}
func equal[T Num](a, b T) bool {
return a == b
}
type MyInt int
func main() {
equal[int](10, 20) //正确
equal[MyInt](10, 20) //错误
}
如果要使上面第二个调用正确,只需要修改Num中对int的定义即可
type Num interface {
~int | float64
}