在城堡里,我遇见你,城堡在我的美梦里;
在城市里,我失去你,城市在我的现实里
人在快乐的时候是不会询问人生的意义这样具有生活意味和哲学深度的问题
在2023.8这个时间,go1.21发布了。相信go的每次大的发布,都会伴随着更简单丝滑的开发体验。闲言少叙,我们来看看有哪些丝滑的体验。
内置的清空函数
在1.21之前,当我们想要清空一个slice或者map 我们必须手动写一个循环去一个个的删除,现在可以直接使用clear函数,一行代码清空
m := map[string]string{"foo": "bar", "hello": "girl", "gopher": "go"}
clear(m) // m={}
s := []string{"foo", "bar"}
clear(s) // s=["", ""]
结构化的日志包slog
在此之前,已经出现了很多的日志包,比如zap,然而go标准库没有一个专门的日志框架来标准化日志的操作总归是不好的。slog意为structured log
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
// Use it like this:
logger.Info("hello", "counter", 3)
2个新的包,slices和maps
slices和maps是1.21新增的2个包,封装了常用的对slice和map的操作
test := []string{"A", "C", "B", "A"}
// Use the new slice functions
slices.IsSorted(test) // false 是否是有顺序的
slices.Sort(test) // [A A B C] 对元素排序
//2个slice比较 返回0表示相等
slices.Compare(test, []string{"A", "A", "B", "C"}) // 0
//2分搜索
slices.BinarySearch(test, "B") // 1 true
//翻转slice
slices.Reverse(test) // [C B A A]t
//在指定索引位置插入元素
slices.Insert(test, 1, "D") // [A D A B C]
//压缩
slices.Compact(test) // [A C B A]
这里我们可以总结谷歌工程师的一个习惯:工具类的命名习惯一般在命名上多加一个s。 比如strings,slices,maps,熟悉java的同学如果知道guava框架,就不会对这点陌生了。
下面举些栗子
Lists 类似go的slices
Maps 类似go的maps
Objects 对象的一些工具方法
Sets set的工具方法
Ints int的工具方法
其实在Java源码包里面也有类似的命名习惯
如Arrays
Collections
Objects
同时还需要注意的是这些工具已经支持泛型了
//切片s里面是否包含元素v 需要元素都实现了 comparable接口
//也就是元素是可比较的
func Contains[E comparable](s []E, v E) bool
//自定义函数决定如何比较
func ContainsFunc[E any](s []E, f func(E) bool) bool
//删除元素
func Delete[S ~[]E, E any](s S, i, j int) S
从这些函数的定义来看已经出现了泛型的表达
我们来看一个index的实现
// Index returns the index of the first occurrence of v in s,
// or -1 if not present.
func Index[E comparable](s []E, v E) int {
for i, vs := range s {
if v == vs {
return i
}
}
return -1
}
maps的使用
var (
m1 = map[int]int{1: 2, 2: 4, 4: 8, 8: 16}
m2 = map[int]string{1: "2", 2: "4", 4: "8", 8: "16"}
)
func main() {
//Keys获取map所有的key
fmt.Println(maps.Keys(m1))
fmt.Println(maps.Keys(m2))
//Values获取map所有的value
fmt.Println(maps.Values(m1))
fmt.Println(maps.Values(m2))
//map之间的相等比较
fmt.Println(maps.Equal(m1, map[int]int{1: 2, 2: 4, 4: 8, 8: 16}))
maps.Clear(m1)
fmt.Println(m1)
m3 := maps.Clone(m2)
fmt.Println(m3)
}
内置的min,max函数
从名字上看就是获取2个数字谁最大,谁最小。是一个很小的功能函数,但是它可以传2个以上的参数来参与比较,这样看是不是觉得min,max还是挺强大的
m := min(x, y) // m is the smaller of x and y
c := max(1, 2.0) // c == 2.0
t := max("", "foo", "bar") // t == "foo"
总结 go社区在改进go的过程中,总是在寻找简单和可维护性之间的平衡,这个原则也可以用到我们日常开发中。寻找一种简单不失优雅的设计和编码风格。