关于golang:尝鲜Go-118中范型版本的map和slice

7次阅读

共计 2356 个字符,预计需要花费 6 分钟才能阅读完成。

大家最近都关注到了 Go 1.18 会反对范型的音讯了吧。

作为 Golang 的内置类型,大家都期待 map 和 slice 反对范型后,能够简化很多的判断逻辑,比方 Equal 逻辑等等。

几天前,Go 范型的规范库曾经提交了,且能够试用了:

大家也能够读一下对应的代码:https://cs.opensource.google/…

废话不多说,咱们看下如何尝试范型版本的 map 和 slice 吧!

如何应用 Go 1.18?

Golang 官网链接只有 1.17 版本的下载,那么咱们如何能力应用 1.18 版本的 Golang 呢?

网上翻了翻,有人提供了 Golang 1.18 版本的 Docker 镜像 seongwoohong/golang-nightly:1.18,而且保障保护到 1.18 版本正式公布:

那么咱们就能够用如下命令启动一个 go1.18 的编译环境了:

$ docker run --rm -it -v $PWD:/root/go-generics seongwoohong/golang-nightly:1.18 sh
# cd /root/go-generics/
~/go-generics #

尝试 maps

翻了下 maps 的代码和测试用例,用上面的代码演示下 maps 的性能:

package main

import (
    "fmt"
    "strconv"

    "golang.org/x/exp/maps" // v0.0.0-20211129234152-8a230f1f7d7a
)

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"}

    // Keys 办法返回 map 的所有键
    // 如果没有范型,那么对于每种 map,都须要写 Keys 办法,当初只须要一个
    fmt.Printf("m1 Keys:\t%#v\n", maps.Keys(m1))
    fmt.Printf("m2 Kyes:\t%#v\n", maps.Keys(m2))

    // Values 办法返回 map 的所有值
    fmt.Printf("m1 Values:\t%#v\n", maps.Values(m1))
    fmt.Printf("m2 Values:\t%#v\n", maps.Values(m2))

    // 判断 map 是否相等
    fmt.Println("m1==m1?\t", maps.Equal(m1, m1))
    fmt.Println("m2==m2?\t", maps.Equal(m2, m2))
    //fmt.Println(maps.Equal(m1, m2))
    // map[int]int 与 map[string]string 无奈比拟

    // 判断 map 是否相等(手动指定判断逻辑)fmt.Println("m1==m3?\t", maps.EqualFunc(m1, m3, func(v1 int, v2 string) bool {return strconv.Itoa(v1) == v2
    }))

    // 还有一些 Clear、Clone、Copy、DeleteFunc,都是见名知义的函数
}

而后编译执行看看:

# 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 的性能:

package main

import (
    "fmt"
    "strconv"

    "golang.org/x/exp/slices" // v0.0.0-20211129234152-8a230f1f7d7a
)

func main() {var s1 = []int{1, 2, 3}
    var s2 = []string{"1", "2", "3"}

    // 判断 slice 是否相等
    fmt.Println("s1==s1?\t", slices.Equal(s1, s1))
    fmt.Println("s2==s2?\t", slices.Equal(s2, s2))
    //fmt.Println(slices.Equal(s1, s2))
    //[]int 与 []string 无奈比拟

    // 判断 slice 是否相等(手动指定判断逻辑)fmt.Println("s1==s2?\t", slices.EqualFunc(s1, s2, func(v1 int, v2 string) bool {return strconv.Itoa(v1) == v2
    }))

    // 在 slice 中查找某个元素
    fmt.Printf("s1[%v]=%d\n", slices.Index(s1, 2), 2)
    fmt.Printf("s1[%v]=%d\n", slices.Index(s1, 999), 999)

    // 还有一些 Clear、Clone、Copy、DeleteFunc,都是见名知义的函数
}

同样能够编译通过并执行:

# 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 做的更好些。

正文完
 0