我写了一些代码,其中一个函数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
您可以在整个 Tour和Go 博客上了解更多信息。

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)
}
- 2 回答
- 0 关注
- 112 浏览
添加回答
举报
0/150
提交
取消