早在 2022 年 10 月,rsc 就有一个提案:spec: add clear(x) builtin, to clear map, zero content of slice,主要原因是干掉类似这样的代码:
for k := range m {
delete(m, k)
}
目前 Go tip 版本已经有 clear 函数了。它的函数签名如下:
func clear[T ~[]Type | ~map[Type]Type1](t T)
clear 可以清空切片或 map 类型的值,将其底层元素全部置为零值,并保持其切片长度和容量不变。
归纳起来,clear
函数能够解决以下几类问题:
s = s[:0]
或 s = nil
等方式,这些方式不够直观和一致,而且可能会导致内存泄露或性能下降。使用 clear(s)
可以更简洁和高效地完成清空操作,并且保留底层内存。for k := range m { delete(m, k) }
或 m = nil
等方式,这些方式不够优雅和安全,而且可能会导致内存浪费或竞争条件。使用 clear(m)
可以更方便和安全地完成清空操作。总之,当需要将切片或映射类型的值清空时,都可以使用 clear
函数。但是需要注意以下几点:
clear
函数只能接受切片或 map 类型的值作为参数,不能接受指向切片或映射类型的值的指针作为参数。如果传入指针,则会导致编译错误,因为类型不匹配。clear
函数可以接受符合切片或 map 的约束泛型作为参数,这样可以实现多态性。约束泛型是一种限制类型参数取值范围的接口,切片或 map 的约束泛型分别是 ~[]Type
和 ~map[Type]Type1
,其中 Type
和 Type1
是类型参数。clear
函数不支持其他类型的值,例如通道、结构体等。如果想要清空这些类型的值,需要自己定义一个清空函数,或者使用其他方式。clear
函数传入一个字面量不会导致编译错误,但也没有任何效果,因为字面量是不可寻址的值。例如 clear([]int{1, 2, 3})
或 clear(map[string]string{"foo": "bar"})
。以下是一些使用 clear
函数的示例,因为 Go 1.21.0 还未发布,要正常运行下面代码,请安装 Go tip 版本。或者使用 Go playground 运行,地址:https://go.dev/play/p/dgf62WVxPxg?v=gotip。
package main
import (
"fmt"
)
func main() {
// clear a slice
s := []int{1, 2, 3, 4}
fmt.Println(s) // [1 2 3 4]
clear(s)
fmt.Println(s) // [0 0 0 0]
// clear a map
m := map[string]string{"foo": "bar", "baz": "qux"}
fmt.Println(m) // map[foo:bar baz:qux]
clear(m)
fmt.Println(m) // map[]
// clear a constrained type parameter
type MySlice []int
type MyMap map[string]int
var ms MySlice = []int{5, 6, 7, 8}
var mm MyMap = map[string]int{"one": 1, "two": 2}
fmt.Println(ms) // [5 6 7 8]
fmt.Println(mm) // map[one:1 two:2]
clear(ms)
clear(mm)
fmt.Println(ms) // [0 0 0 0]
fmt.Println(mm) // map[]
}
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8