本次内容:
- 使用slice和map的内置函数
- 避免不必要的类型转换
- 优雅的字符串拼接方式
正文:
使用slice和map的内置函数
在Go语言中,append()
, copy()
, len()
, cap()
函数是处理切片(slice)时非常常用的内置函数,但它们并不直接涉及 delete()
,因为 delete()
是用于处理映射(map)的内置函数,用于删除映射中的键值对。下面是每个函数的作用说明:
1)append(slice []Type, elems ...Type) []Type
:用于向切片末尾追加一个或多个元素,并返回一个新的切片(可能是原切片的扩展,也可能是新分配的切片)。如果切片的空间不足以存储追加的元素,append
会分配一个更大的切片,并将原切片的内容复制到新切片中,然后追加新的元素。
2)copy(dst, src []Type) int
:用于将源切片(src
)的元素复制到目标切片(dst
)中。它会返回复制的元素数量。复制操作会同时考虑dst
和src
的长度,以两者中较短的一个为准。如果dst
有足够的空间存储src
的所有元素,则复制所有元素;否则,只复制能放入dst
中的元素数量。
3)len(v Type) int
:返回其参数的长度。对于切片,它返回切片中元素的数量。
4)cap(v Type) int
:返回其参数的容量。对于切片,它返回切片底层数组的总大小。切片的容量是切片能够增长到的最大长度,而不需要重新分配内存。
5)delete(m map[Type]Type1, key Type)
:用于从映射中删除指定的键值对。如果映射中存在该键,则删除它;如果不存在,则不做任何操作。
总的来说,append()
, copy()
, len()
, cap()
是处理切片时的重要函数,而 delete()
是专门用于处理映射的。
示例:
代码语言:go复制func TestInnerFunc(t *testing.T) {
// append
var nums []int
for i := 0; i < 10; i {
nums = append(nums, i)
}
fmt.Println("nums = ", nums)
// delete
m := make(map[string]string)
m["a"] = "A"
m["b"] = "B"
m["c"] = "C"
fmt.Println("before delete = ", m)
delete(m, "b")
fmt.Println("after delete = ", m)
// copy
var numsc []int
copy(nums, numsc)
fmt.Println("numsc = ", nums)
numsn := make([]int, 10)
numsn[0] = 1
//cap
fmt.Println("nums cap = ", cap(nums))
fmt.Println("numsn cap = ", cap(numsn))
//len
fmt.Println("nums len = ", len(nums))
fmt.Println("numsn len = ", len(numsn))
}
输出:
代码语言:shell复制nums = [0 1 2 3 4 5 6 7 8 9]
before delete = map[a:A b:B c:C]
after delete = map[a:A c:C]
numsc = [0 1 2 3 4 5 6 7 8 9]
nums cap = 16
numsn cap = 10
nums len = 10
numsn len = 10
因为cap()函数是获取数组的容量,因此Go的扩容机制也需要了解下:
Go语言的slice扩容策略在不同的版本和slice容量大小下有所不同,但总体思路是相似的,即创建一个更大的底层数组,并将原始数据复制到新数组中。
Go 1.7及之前版本,如果当前容量小于1024,每次扩容后的容量都会翻倍。如果当前容量大于等于1024,扩容后的容量会按照增长因子(默认为1.25)来计算,即新的容量为原容量的1.25倍。
Go 1.8及之后版本,如果当前容量小于256,每次扩容后的容量都会翻倍。如果当前容量大于等于256且小于4096,扩容后的容量会按照增长因子(这里为1.5)来计算。如果当前容量大于等于4096,扩容后的容量会按照增长因子(默认为1.25)来计算。
避免不必要的类型转换
类型转换是昂贵的操作,应该避免在性能敏感的代码中进行不必要的类型转换。
示例:避免在循环中进行类型转换
代码语言:go复制// 不推荐
var nums []interface{} = [...]interface{}{1, 2, 3, 4}
for _, num := range nums {
if v, ok := num.(int); ok {
fmt.Println(v)
}
}
// 推荐(如果类型已知)
var nums []int = [...]int{1, 2, 3, 4}
for _, num := range nums {
fmt.Println(num)
}
优雅的字符串拼接方式
对于大量的字符串拼接操作,使用strings.Builder
或(在Go 1.10及以后)编译器优化的
操作符通常比使用fmt.Sprintf
更高效。
示例:
代码语言:go复制const (
hello = "Hello "
world = "World"
sign = "!"
)
// 推荐
func userBuilder() string {
builder := strings.Builder{}
builder.WriteString(hello)
builder.WriteString(world)
builder.WriteString(sign)
return builder.String()
}
// 推荐
func userPlus() string {
return hello world sign
}
// 不推荐
func userFmt() string {
return fmt.Sprintf("%s%s%s", hello, world, sign)
}
本篇结束~