我编写了一些代码,其中函数f将切片s作为参数并修改它而不返回它。
由于切片可以被视为对底层数组的引用,因此我认为切片实际上会在该函数的范围之外进行修改,但事实并非如此。
下面的代码就是一个例子(https://play.golang.org/p/Y5JUmDtRXrz)。
package main
import (
"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)
}
Run Code Online (Sandbox Code Playgroud)
pop(s)实际上返回0,这是预期的。但在输出中s仍然有0第一个元素。
0 [0 1 2 3]
Program exited.
Run Code Online (Sandbox Code Playgroud)
为什么?我该如何解决这个问题?
这里发生了两件不同的事情,两者都阻止了这种行为如您所期望的那样:
func pop(s []int) int {
first, s := s[0], s[1:]
Run Code Online (Sandbox Code Playgroud)
第一个问题(也是更简单的)是您s在这里定义一个新的局部变量,它会隐藏您的函数参数s。
其次,切片确实指向底层数组,但切片仍然通过副本传递,就像其他所有内容一样。这意味着:
s = s[1:]
Run Code Online (Sandbox Code Playgroud)
修改s 的副本以在基础数组上拥有不同的窗口。这不会改变调用者中的切片。但是,如果您更改底层数组中的值,这将反映在调用方中,例如:
s[1] = 42
Run Code Online (Sandbox Code Playgroud)