In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution.
官方文檔已經明確說明:Go裏邊函數傳參只有值傳遞一種方式: 值傳遞
那麼爲何會引起Go的值拷貝的討論?函數
用下面的代碼作一下展現lua
package main import ( "fmt" ) func main() { arr := [5]int{0, 1, 2, 3, 4} s := arr[1:] changeSlice(s) fmt.Println(s) fmt.Println(arr) } func changeSlice(arr []int) { for i := range arr { arr[i] = 10 } }
輸出結果spa
[10 10 10 10] [0 10 10 10 10]
若是Go是值拷貝的,那麼我修改了函數 changeSlice
裏面的slice s
的值,爲何main函數裏面的slice
和 array
也被修改了指針
以上圖爲例,a 是初始變量,b 是引用變量(Go中並不存在),p 是指針變量
變量a被拷貝後,地址發生了變化,地址上存儲的是原先地址存儲的值 10
變量p被拷貝後,地址發生了變化,地址上存儲的仍是原先地址存儲的值 )0X001, 而後按照這個地址去查找,找到的是 0X001 上面存儲的值調試
因此,當你去修改拷貝後的*p的值,其實修改的仍是0X001地址上的值,而不是 拷貝後a的值code
那麼咱們接下來看slice,slice在實現的時候,實際上是對array的映射,也就是說slice存對應的是原array的地址,就相似於p與a的關係,那麼整個slice拷貝後,拷貝後的slice中存儲的仍是array的地址,去修改拷貝後的slice,其實跟修改slice,和原array是同樣的blog
咱們用下面一個例子,實現如下咱們上面的想法rem
package main import ( "fmt" ) func main() { var a *int b := 10 a = &b change(a) fmt.Println(a, b) } func change(a *int) { *a = 30 }
打印結果文檔
0xc000096000 30
符合猜測it
這裏的東西,其實用dlv調試會看的很方便,有興趣能夠動一下手
Go的拷貝都是值拷貝,只是slice中存儲的是原array的地址,因此在拷貝的時候,實際上是把地址拷貝的新的slice,那麼此時修改slice的時候,仍是根據slice中存儲的地址,找到要修改的內容