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 回复

谢谢!)

更多关于Golang中的切片与底层数组原理详解的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


因为在第一种情况下,底层数组需要增长,并且为 slice2 发生了重新分配。

对于第二种情况,数组不需要增长,因此两个切片指向相同的起始位置,但具有不同的长度。

在Go语言中,切片的行为取决于其底层数组的容量。当切片容量足够时,append操作会共享底层数组;当容量不足时,会分配新数组。

第一个例子中,slice1初始容量为1。第一次append时容量不足,分配新数组[1,3]。第二次append时,slice1的容量仍为2(长度2),append(slice1,4)需要容量3,因此分配新数组[1,3,4]。此时slice1slice2使用不同数组,修改互不影响。

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是否创建新数组取决于切片容量,而不是长度。当容量足够时,操作共享底层数组;容量不足时,分配新数组并复制数据。

回到顶部