b = append(b[:1], b...) 为什么能右移?

238 天前
 lysShub
func TestXxxx(t *testing.T) {
	var b = make([]byte, 128, 512)
	rand.Read(b)

	b1 := slices.Clone(b)
	b = append(b[:1], b...)
	b2 := b[1:]

	require.Equal(t, b1, b2)

	ptr := uintptr(unsafe.Pointer(unsafe.SliceData(b)))
	ptr2 := uintptr(unsafe.Pointer(unsafe.SliceData(b2)))
	require.Equal(t, ptr+1, ptr2)
}

第一步:把 b[0]放入 b[1], 这没问题

第二步:把 b[1]放入 b[2], 可是这是的 b[1]在第一步被覆盖了,这样推导下去,整个 b[i]都会变为 b[0] ?

1948 次点击
所在节点    Go 编程语言
10 条回复
MoYi123
238 天前
我觉得大概率是编译成 memmove 了.
lysShub
238 天前
@MoYi123 看了下汇编,确实有 memmove
my3157
238 天前
和前面的没啥关系, b 和 b2 本来就是引用了同一个底层数组的不同位置而已

b = append(b[:1], b...)
b2 := b[1:]
lasuar
238 天前
不明白为什么产生问题。。
kandaakihito
238 天前
额。。。?我是建议楼主先去看看 slice 的结构体相关的八股文,看完就理解了。

简单来说,此时 b 和 b2 指向的切片内存地址是同一块,你这上面的操作全都在同一段地址上进行。
ns09005264
238 天前
只是把数组 b 的第一个元素移动到最后,完了以后在数组 b 上新创建了切片 b2 ,只比数组 b 少了第一个元素。
后面用 SliceData 获取数组底层的第一个元素指针,数组 b 的指针+1 后就跑到底层的第二个元素指针,切片 b2 的第一个元素指针就是数组 b 的第二个元素。
lysShub
238 天前
楼上几个题也不读,正是因为 slice 的数据是指针引用才会有这个问题
lysShub
238 天前
实际证明,append(v, slice...) 使用 memmv 不仅是出于性能, 为了正确性也必须这么做。

如果把它编译为 for 循环结果就是错误的
func TestZzzzz(t *testing.T) {
var b = make([]byte, 128, 512)
rand.Read(b)

b1 := slices.Clone(b)

b2 := b[:1]
{ // append
for _, e := range b {
b2 = append(b2, e)
}
}
b2 = b2[1:]

require.Equal(t, b1, b2)
}
my3157
238 天前
@lysShub #8 根本不是一个问题啊

后面这个还是共享底层数组的问题, b2 := b[:1] 只是对 b 底层数组的引用, 后面循环修改 b2 相当于修改 b
ns09005264
237 天前
你的疑惑似乎都是切片的 append 带来的,可以找找切片的详细资料看看。
```
var b = make([]byte, 10, 10)
b2 := b[1:2] // 新切片从 b 的位置 1 开始,到 1 结束,长度只有 1, 但是容量是 b 的容量减开始的位置 1 等于 9
fmt.Println("b: ", b) // [0 0 0 0 0 0 0 0 0 0]
// b2 追加新元素,但容量是 10-1=9 ,长度是 1, 不触发扩容,改变了原切片 b 的第三元素
b2 = append(b2, 7)
fmt.Println("b: ", b) // [0 0 7 0 0 0 0 0 0 0]
// b3 容量是 1,长度是 1, 改变 b3 第一个元素会影响原切片 b 。
b3 := b[9:]
b3[0] = 6
b3 = append(b3, 8)
fmt.Println("b: ", b) // [0 0 7 0 0 0 0 0 0 6]
// 由于 b3 上面追加了新元素,触发扩容,b3 开辟了新空间,和原切片没有关系了,改变第一个元素不影响原切片
b3[0] = 5
fmt.Println("b: ", b) // [0 0 7 0 0 0 0 0 0 6]
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1116346

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX