为了账号安全,请及时绑定邮箱和手机立即绑定

改变作为参数传递给 Go 中函数的切片

改变作为参数传递给 Go 中函数的切片

Go
MMTTMM 2022-07-11 14:58:23
我写了一些代码,其中一个函数f将切片s作为参数并修改它而不返回它。由于切片可以被视为对底层数组的引用,我认为切片实际上会在该函数的范围之外进行修改,但事实并非如此。下面的代码就是一个例子(https://play.golang.org/p/Y5JUmDtRXrz)。package mainimport (    "fmt")func pop(s []int) int {    first, s := s[0], s[1:]    return first}func main() {    s := []int{0, 1, 2, 3}    first := pop(s)    fmt.Println(first, s)}pop(s)实际上返回0,这是预期的。但是在输出中s仍然有0它的第一个元素。0 [0 1 2 3]Program exited.为什么?我怎么能解决这个问题?

2 回答

?
冉冉说

TA贡献1877条经验 获得超1个赞

这里发生了两件不同的事情,两者都阻止了它的行为如你所料:

func pop(s []int) int {
    first, s := s[0], s[1:]

第一个(也是更简单的)问题是你在s这里定义了一个新的局部变量,它会影响你的函数参数s

其次,切片确实指向一个底层数组,但切片仍然通过副本传递,就像其他所有内容一样。这意味着:

s = s[1:]

修改您的 s 副本以在基础数组上具有不同的窗口。这不会改变调用者中的切片。但是,如果您更改底层数组中的值,这反映在调用者中,例如:

s[1] = 42

您可以在整个 TourGo 博客上了解更多信息。


查看完整回答
反对 回复 2022-07-11
?
catspeake

TA贡献1111条经验 获得超0个赞

该行first, s := s[0], s[1:]创建了一个新变量s,因为您使用的是:=. 最重要的是,如果要修改切片,则需要通过指针传递它。


通过值传递它,它将引用相同的底层数组,但切片本身是一个副本。因此,对底层数组的更改将反映在 中main,但对切片本身的更改不会。


这是一个通过指针传递切片的示例。


package main


import (

    "fmt"

)


func pop(s *[]int) int {

    first := (*s)[0]

    *s = (*s)[1:]

    return first

}


func main() {

    s := []int{0, 1, 2, 3}

    first := pop(&s)

    fmt.Println(first, s)

}


查看完整回答
反对 回复 2022-07-11
  • 2 回答
  • 0 关注
  • 112 浏览
慕课专栏
更多

添加回答

代码语言

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号