golang slice切片扩容问题?

新手上路,请多包涵
package main
import "fmt"

func main() {
    s3:=make([]int,2,10)
    fmt.Println(s3)
    Test2(s3)
    fmt.Println(s3)

    s4:=s3[0:10]
    fmt.Println(s4)
}
func Test2(s []int){
    s=append(s,6)
    s=append(s,6)
    s=append(s,6)
    fmt.Println(s)
}

得出的结果是:
[0 0]
[0 0 6 6 6]
[0 0]
[0 0 6 6 6 0 0 0 0 0]
请问一下,第三个结果为什么是[0 0],而不是 [0 0 6 6 6] 呢,
在Test2 函数中,使用append的时候,并没有扩容,添加的数据还在底层数组的容量中, 那为啥在 Test2函数之后 s3是[0 0]
即使是在原有的容量基础上扩容,那为啥 s4:=s3[0:10] 是[0 0 6 6 6 0 0 0 0 0],按理来说在函数中扩容之后和外面的没关系了,那s4 应该是[0 0]才对

阅读 813
3 个回答

s3 跟 Test2 中的 s 是两回事。

Test2 中 append 没有扩容,只是改变了 slice 的长度。但是它改变的是 s 的长度,而不是 s3 。它们依然共享这一个数组,但是他们有不同的长度。在 Test2 之后,数组中已经的是 [0,0,6,6,6,0,...] ,但是由于 s3 的长度还是 2 ,所以打出来还是 [0,0] 。

s4 打出了数组中的全部内容。

之前的回答事错误的;

本地debug了一下,具体可以看控制台。

原因是Test2中slice的len变了,地址没变,但是main中s的len还没有变,所以出现读的时候len还是2,读出来是在s初始化(make)时候的长度。

手动通过s[0:10]设定获取范围以后,读到Test2的append值。

image.png

下面代码就可以一致了。

package main

import (
 "fmt"
)

func main() {
 s := make([]int, 2, 10)
 fmt.Printf("%v %d %p \n", s, len(s), s)
 Test2(&s)
 fmt.Printf("%v %d %p \n", s, len(s), s)
}

func Test2(s *[]int) {
 fmt.Printf("%v %d %p \n", s, len(*s), s)
 *s = append(*s, 6)
 *s = append(*s, 6)
 *s = append(*s, 6)
 fmt.Printf("%v %d %p \n", *s, len(*s), s)
}

首先,go所有的传递都是值传递,如果想要修改原变量,需要使用指针

而针对slice,他的结构是
image.png

所以,对于slice传递的时候,可以看到 传递的是一个struct结构体,这个结构体包含 Array的地址,Len和Cap三个属性,

func Test2(s []int){

这里的s,只是一个跟s2数据相同的另一个结构体了,可以debug看出来,他们的地址是不一样的,而两个struct指向的底层Array的地址都是同一个,也就可以解释,为啥底层数据修改了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题