关于golang slice append 操作的问题

来源:10-1 后端接口优化思路

白小九jiu

2020-07-03

cap 老师好,我在进行golang slice操作的使用时,遇到了这样一个问题
如图,代码是对 temp 里的字符串进行匹配,如果等于 “foo” 的话,打印去掉这个字符串后的数组ret,但是我不希望 temp 的值发生改变,可是运行代码发现 temp 的值改变了,应该是在执行 append 的时候,我不能理解为什么 temp 会被修改。图二是运行结果,temp 的值从【“foo”,“bar”,“zoo”】变成了【“bar”,“zoo”,“zoo”】。
希望老师帮忙解答一下。
进行append的代码
运行结果

temp := []string{"foo", "bar", "zoo"}

	for i := 0; i < len(temp); i++ {
		if temp[i] == "foo" {
			fmt.Println(temp[:i], "+++", temp[i+1:])

			ret := append(temp[:i], temp[i+1:]...)

			fmt.Println(temp[:i], "+++", temp[i+1:])

			fmt.Println("temp:", temp, "ret:",ret )
			break
		}
	}
	fmt.Println(temp)
写回答

1回答

Cap

2020-07-07

同学你好,这里 go 的 slice 有个很大的坑,

就拿这个来举例:ret:=append(temp[:n],temp[1:2]...)

1.首先这个 append + ... 的操作时 slice 的合并操作;

2.第一个参数 使用 temp[:n]获取切片时候 获取的是 n+1 位的地址;

3.这样就是temp[:n] 和 temp[1:2] 进行切片的合并;

4.这里当 ret的capacity 小于 temp的 capacity 时候,底层使用的是同一个切片,ret指针地址和temp地址一样(len不一样,capacity相同)。这时候temp值被修改;

5.当 ret最终结果的容量 cap acity 大约 temp的容量时,这里的ret 会自动扩容 ret的容量(capacity*2),这时ret和temp不再是同一个底层切片,不会影响原有temp的值;


0
0

全流程开发 GO实战电商网站高并发秒杀系统

运用架构设计与系统化思维,从容应对不同流量等级的“秒杀”场景

1462 学习 · 443 问题

查看课程