go-slice指针会一致吗?
slice的底层数组指针在某些操作下会保持一致,在其他操作下则可能会发生改变。
在Go语言中,slice是一个引用类型,它包含了指向底层数组的指针、slice的长度以及它的容量。
通过某些操作修改slice时(如切片、append等),底层数组的指针可能会保持不变,也可能会发生改变。
切片操作
对一个slice进行切片操作时(即获取slice的一个子集),结果slice与原slice将共享同一个底层数组。这意味着它们的指针会指向同一个地址,但是切片操作后的slice将拥有不同的长度和容量。
a := []int{1, 2, 3, 4}
b := a[1:3]
// a和b共享同一个底层数组,但是它们的长度和容量不同。
通过append增加元素
当通过append函数给slice增加元素,且未超过其容量时,新元素将被添加到底层数组中,这时slice的指针不会改变,只是长度增加了。
如果在添加新元素时超过了原slice的容量,Go运行时将分配一个新的、更大的底层数组,并复制原有元素到这个新数组中,然后添加新元素。
这种情况下,slice的指针会指向这个新的底层数组的地址,因此指针会发生改变。
直接修改slice元素
如果直接修改slice的元素,比如a[1] = 10,这不会影响到slice本身的指针、长度或容量,
因为没有进行重新分配或切片操作,只是修改了底层数组已经存在的元素。
如何检查slice在进行操作后指针是否发生了变化
仅仅是为了进行检查,使用unsafe包中的功能来获取或比较指针是不推荐的
package main
import (
"fmt"
"unsafe"
)
func main() {
a := []int{1, 2, 3}
fmt.Printf("Original slice pointer: %p
", &a[0])
b := a[:2]
fmt.Printf("After slicing pointer: %p
", &b[0])
c := append(a, 4)
fmt.Printf("After appending within capacity pointer: %p
", &a[0])
fmt.Printf("New slice pointer: %p
", &c[0])
d := append(a, 5, 6, 7) // Assuming this exceeds original capacity
fmt.Printf("After appending beyond capacity pointer: %p
", &d[0])
}
func slicePointer(slice []int) unsafe.Pointer {
return unsafe.Pointer(*(*uintptr)(unsafe.Pointer(&slice)))
}
slice的底层数组指针在某些操作下会保持一致,在其他操作下则可能会发生改变。