大家最近都关注到了Go 1.18会支持范型的消息了吧。
作为Golang的内置类型,大家都期待map和slice支持范型后,可以简化很多的判断逻辑,比如Equal逻辑等等。
几天前,Go范型的标准库已经提交了,且可以试用了:
大家也可以读一下对应的代码:https://cs.opensource.google/go/x/exp/+/master:maps/maps.go
废话不多说,我们看下如何尝试范型版本的map和slice吧!
如何使用Go 1.18?
Golang 官网链接只有1.17版本的下载,那么我们如何才能使用1.18版本的Golang呢?
网上翻了翻,有人提供了Golang 1.18版本的Docker镜像 seongwoohong/golang-nightly:1.18
,而且保证维护到1.18版本正式发布:
那么我们就可以用如下命令启动一个go1.18的编译环境了:
1 2 3
| $ docker run --rm -it -v $PWD:/root/go-generics seongwoohong/golang-nightly:1.18 sh # cd /root/go-generics/ ~/go-generics #
|
尝试maps
翻了下maps的代码和测试用例,用下面的代码演示下maps的功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package main
import ( "fmt" "strconv"
"golang.org/x/exp/maps" )
func main() { var m1 = map[int]int{1: 2, 2: 4, 4: 8, 8: 16} var m2 = map[string]string{"1": "2", "2": "4", "4": "8", "8": "16"} var m3 = map[int]string{1: "2", 2: "4", 4: "8", 8: "16"}
fmt.Printf("m1 Keys:\t%#v\n", maps.Keys(m1)) fmt.Printf("m2 Kyes:\t%#v\n", maps.Keys(m2))
fmt.Printf("m1 Values:\t%#v\n", maps.Values(m1)) fmt.Printf("m2 Values:\t%#v\n", maps.Values(m2))
fmt.Println("m1==m1?\t", maps.Equal(m1, m1)) fmt.Println("m2==m2?\t", maps.Equal(m2, m2))
fmt.Println("m1==m3?\t", maps.EqualFunc(m1, m3, func(v1 int, v2 string) bool { return strconv.Itoa(v1) == v2 }))
}
|
然后编译执行看看:
1 2 3 4 5 6 7 8 9
| # go build -gcflags="-G=3 -lang=go1.18" # ./m m1 Keys: []int{1, 2, 4, 8} m2 Kyes: []string{"8", "1", "2", "4"} m1 Values: []int{2, 4, 8, 16} m2 Values: []string{"16", "2", "4", "8"} m1==m1? true m2==m2? true m1==m3? true
|
尝试slices
同样,翻翻slices的代码和测试用例,可以用下面的代码演示下slices的功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package main
import ( "fmt" "strconv"
"golang.org/x/exp/slices" )
func main() { var s1 = []int{1, 2, 3} var s2 = []string{"1", "2", "3"}
fmt.Println("s1==s1?\t", slices.Equal(s1, s1)) fmt.Println("s2==s2?\t", slices.Equal(s2, s2))
fmt.Println("s1==s2?\t", slices.EqualFunc(s1, s2, func(v1 int, v2 string) bool { return strconv.Itoa(v1) == v2 }))
fmt.Printf("s1[%v]=%d\n", slices.Index(s1, 2), 2) fmt.Printf("s1[%v]=%d\n", slices.Index(s1, 999), 999)
}
|
同样可以编译通过并执行:
1 2 3 4 5 6 7
| # go build -gcflags="-G=3 -lang=go1.18" # ./m s1==s1? true s2==s2? true s1==s2? true s1[1]=2 s1[-1]=999
|
总结
相比于Java的范型,Golang真正做到了运行时的范型,能够提升一些效率。
更重要的是,就像王垠之前吐槽的那样,Java的数组不支持范型,这让Java的类型系统显得不是那么完备。在这一点上,Golang做的更好些。