go1。18泛型初体验
go 1.18泛型初体验
go.1.18beta版发布,众所周知这个go.1.18版本会默认启用go泛型。这个版本也号称go最大的版本改动。 初识golang的泛型
我们写一个demo来看看go的泛型是长啥样 package main import ( "fmt" ) type OrderTypes interface { ~int | ~float32 | ~string } func max[T OrderTypes](x, y T) T { if x > y { return x } return y } func main() { fmt.Println(max(1, 11), max("abc", "eff")) }
ok run 以下代码 $ go run main.go 11 eff
~int | ~float32 | ~string我们看到了新的语法,~是新的操作符,主要用来做类型约束使用, ~int代表类型约束为int类型,~int | ~float32 | ~string则代表约束为 int 或者 float32 或者 string。上面额例子中,这三个类型刚好是可以比较的能进行 ">" 操作的。
当然上面的代码是演示用的,在真正的项目中我们应该使用标准constraints提供的Ordered来做约束。 import ( "constraints" ) func max[T constraints.Ordered](x, y T) T { if x > y { return x } return y }
constraints标准库定义了一下常用的类型约束,如Ordered,Signed,Unsigned,Integer,Float。 提高生产力的泛型
我们通过下面的例子来看看泛型,如何提高我们的生产力。我们将为所有slice类型添加三件套map,reduce,filter func Map[Elem1, Elem2 any](s []Elem1, f func(Elem1) Elem2) []Elem2 { r := make([]Elem2, len(s)) for i, v := range s { r[i] = f(v) } return r } func Reduce[Elem1, Elem2 any](s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 { r := initializer for _, v := range s { r = f(r, v) } return r } func Filter[Elem any](s []Elem, f func(Elem) bool) []Elem { var r []Elem for _, v := range s { if f(v) { r = append(r, v) } } return r } func Silce() { sliceA := []int{3, 99, 31, 63} //通过sliceA 生成sliceB sliceB := Map(sliceA, func(e int) float32 { return float32(e) + 1.3 }) fmt.Println(sliceB) //找最大值 max := Reduce(sliceB, 0.0, func(a, b float32) float32 { if a > b { return a } return b }) fmt.Println(max) //过滤sliceA中大于30的组成新的slice sliceC := Filter(sliceA, func(e int) bool { if e > 30 { return true } return false }) fmt.Println(sliceC) } func main() { Silce() } $ go run main.go [4.3 100.3 32.3 64.3] 100.3 [99 31 63] 带泛型的struct
接下来我们看一下带泛型的struct //定义的时候需要加约束 type Student[T constraints.Unsigned] struct { Age T } //后续struct方法编写的时候 约束就不能写了 func (s *Student[T]) GetAge() T { return s.Age }
我们初始化带泛型的结构图 age := uint(3) s := &Student[uint]{Age: age} fmt.Println(s.GetAge()) //3 s1 := &Student[uint16]{Age: uint16(age)} fmt.Println(s1.GetAge()) //3 总结
go的泛型目前还没有官方推荐的最佳实践,标准库的代码也基本没改成泛型。但总归走出支持泛型这一步,后续丰富标准库应该是后面版本的事情了。再看go2代码的时候发现一个有意思的东西--orderedmap。感兴趣的同学可以去看看。