Golang Go语言中 slice 在 append 不同情况下的理解

发布于 1周前 作者 h691938207 来自 Go语言

Golang Go语言中 slice 在 append 不同情况下的理解

Q 群里讨论起来 slice 的传递,才发现有坑 = =

看了网上的一些文章。slice 在传入函数后 append 会有坑 下面是我的理解,不知道恰不恰当。

一种情况是 cap 够,不扩容

func main() {
    sliceA := make([]int, 3, 4)
    sliceA[0] = 0
    sliceA[1] = 1
    sliceA[2] = 2
    fmt.Println(sliceA)
    changeSlice(sliceA)
    fmt.Println(sliceA)
    fmt.Println(sliceA[:4])
}
func changeSlice(slicePass []int) {
    slicePass = append(slicePass, 3)
}

//Output /* [0 1 2] [0 1 2] [0 1 2 3] */

slice 结构中的 len,cap 都是 int,无法在函数里面被改变。 这种情况下指定了一个 len 为 3,cap 为 4 的 slice 。append 完后发现正常输出只会输出前三个数,验证了 len 并没有被改变。而当强制输出第四项时又发现 3 是存在的。 例如截取数组等操作都是这种情况。

也就是说这种情况下 append 对原数组生效,只是由于 len 没有改变而无法呈现出 append 的项。

还有种情况是 cap 不够,slice 扩容

slice 扩容会把扩容后的数组指向新内存,直接与原数组无关了,append 的项也不存在于原数组 大概代码长这样

func main() {
    sliceA := []int{1, 2, 3, 4, 5}
    fmt.Println(sliceA)
    fmt.Printf("%d %p main\n", len(sliceA),sliceA)
    changeSliceA(sliceA)
    fmt.Println(sliceA)
}
func changeSliceA(slicePass []int) {
    slicePass = append(slicePass, 6)
    fmt.Printf("%d %p pass\n", len(slicePass),slicePass)
}

// Output /* [1 2 3 4 5] 5 0xc00000c690 main 6 0xc000016550 pass [1 2 3 4 5] */

所以是 go 中的 slice 在函数中被 append 时数据呈现不变分为两种情况。

一种是 len 未被改变,由传值导致;

一种是指针发生改变,由 slice 的内部扩容实现导致?

这样理解有没有问题?


更多关于Golang Go语言中 slice 在 append 不同情况下的理解的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

回到顶部