Golang中的切片与底层数组原理详解
Golang中的切片与底层数组原理详解
你好。我是新来的,希望问这类问题是可以的。在第一个例子中,slice2 表现得像一个独立的数组。但在第二个例子中情况并非如此。这是为什么呢?
谢谢!
slice1 := []int{1}
slice1 = append(slice1, 3)
slice2 := append(slice1, 4)
slice2[0] = 7
fmt.Println(slice1) // 1 3
fmt.Println(slice2) // 7 3 4
slice1 := []int{1}
slice1 = append(slice1, 2)
slice1 = append(slice1, 3)
slice2 := append(slice1, 4)
slice2[0] = 7
fmt.Println(slice1) // 7 2 3
fmt.Println(slice2) // 7 2 3 4
更多关于Golang中的切片与底层数组原理详解的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
因为在第一种情况下,底层数组需要增长,并且为 slice2 发生了重新分配。
对于第二种情况,数组不需要增长,因此两个切片指向相同的起始位置,但具有不同的长度。
在Go语言中,切片的行为取决于其底层数组的容量。当切片容量足够时,append操作会共享底层数组;当容量不足时,会分配新数组。
第一个例子中,slice1初始容量为1。第一次append时容量不足,分配新数组[1,3]。第二次append时,slice1的容量仍为2(长度2),append(slice1,4)需要容量3,因此分配新数组[1,3,4]。此时slice1和slice2使用不同数组,修改互不影响。
slice1 := []int{1} // 底层数组: [1], len=1, cap=1
slice1 = append(slice1, 3) // 新数组: [1,3], len=2, cap=2
slice2 := append(slice1, 4) // 需要cap=3 > 2,新数组: [1,3,4]
第二个例子中,slice1经过两次append后,容量扩展为4(Go的容量增长策略)。当执行append(slice1,4)时,slice1的容量足够(len=3, cap=4),因此slice2共享底层数组。
slice1 := []int{1} // 底层数组: [1], len=1, cap=1
slice1 = append(slice1, 2) // 新数组: [1,2], len=2, cap=2
slice1 = append(slice1, 3) // 需要cap=3 > 2,新数组: [1,2,3], len=3, cap=4
slice2 := append(slice1, 4) // cap=4足够,共享数组: [1,2,3,4]
验证容量变化:
slice1 := []int{1}
fmt.Printf("初始: len=%d, cap=%d\n", len(slice1), cap(slice1)) // len=1, cap=1
slice1 = append(slice1, 2)
fmt.Printf("第一次append后: len=%d, cap=%d\n", len(slice1), cap(slice1)) // len=2, cap=2
slice1 = append(slice1, 3)
fmt.Printf("第二次append后: len=%d, cap=%d\n", len(slice1), cap(slice1)) // len=3, cap=4
关键点:append是否创建新数组取决于切片容量,而不是长度。当容量足够时,操作共享底层数组;容量不足时,分配新数组并复制数据。

