前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Go小技巧&易错点100例》第二十篇

《Go小技巧&易错点100例》第二十篇

原创
作者头像
盐咔咔
发布2024-08-13 22:41:18
1250
发布2024-08-13 22:41:18
举报
文章被收录于专栏:Go小技巧&易错点100例

本次内容:

  • 使用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)中。它会返回复制的元素数量。复制操作会同时考虑dstsrc的长度,以两者中较短的一个为准。如果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)
}

本篇结束~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用slice和map的内置函数
  • 避免不必要的类型转换
  • 优雅的字符串拼接方式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档