我寫了一些代碼,其中一個函數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 關注
- 124 瀏覽
添加回答
舉報
0/150
提交
取消