golang string slice作为函数参数传递的问题

新手上路,请多包涵
package main

func Sample(args []string) {
    args = append(args, "D", "E")
}

func main() {
    args := []string{}
    args = append(args, "A","B","C")
        Sample(args)
    for _, arg := range args {    
        println(arg)
    }
}

比如在上面这个程序(https://play.golang.org/p/0Ch...)里,我希望Sample函数执行完成之后,args里面的结果是ABCDE,但是真实的结果是ABC。

这跟我对slice的理解不一样啊。

我试了一下,在Sample函数里是可以对里面的string做修改的,

package main

func Sample(args []string) {
    args[2] = "F"
}

func main() {
    args := []string{}
    args = append(args, "A","B","C")
    Sample(args)
    for _, arg := range args {    
        println(arg)
    }
}

上面这个程序(https://play.golang.org/p/Y81...)就把args的最后一个元素改成F了。

还是说因为string也是变长的结构,所以函数在传參的时候就把args的长度固定住了。这是什么原理啊。

阅读 7.7k
3 个回答
func Sample(args []string) {
    println(len(args))
    println(cap(args))
    println(args)
    args = append(args, "D", "E")
    println(len(args))
    println(cap(args))
    println(args)
}

会发生扩容,args的地址已经改了,内部的数组也已经变了。
但是go中只有值传递,所以外面的args还是引用前面的数组。
可以将args返回解决。

package main

func Sample(args *[]string) {
    *args = append(*args, "D", "E")
}

func main() {
    args := []string{}
    args = append(args, "A", "B", "C")
    Sample(&args)
    for _, arg := range args {
        println(arg)
    }
}

最简单的办法就是这样了
另一种方式,就是在Sample方法中,返回数组
其实就是值传递和指针传递的问题,你可以去搜一些相关资料,看一下就明白了

首先golang只有值传递, slice传递的是reflect.SliceHeader的copy, 其中的Data字段指向底层数组, append扩容导致底层数组重新分配,即Data的指向发生了变化.args[2] = "F"仅修改了底层数组的值,Data的指向不变.

你可看看golang官方的slice介绍Go Slices: usage and internals.

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