Go沒有引用傳遞和引用類型!!! 很多人有個誤區,認為涉及Go切片的參數是引用傳遞,或者經常聽到Go切片是引用類型這種說法,今天我們就來說一下方面的問題。 什麼是值傳遞? 將實參的值傳遞給形參,形參是實參的一份拷貝,實參和形參的記憶體地址不同。函數內對形參值內容的修改,是否會影響實參的值內容,取決於參 ...
Go沒有引用傳遞和引用類型!!!
很多人有個誤區,認為涉及Go切片的參數是引用傳遞,或者經常聽到Go切片是引用類型這種說法,今天我們就來說一下方面的問題。
什麼是值傳遞?
將實參的值傳遞給形參,形參是實參的一份拷貝,實參和形參的記憶體地址不同。函數內對形參值內容的修改,是否會影響實參的值內容,取決於參數的本身
什麼是引用傳遞?
將實參的地址傳遞給形參,函數內對形參值內容的修改,將會影響實參的值內容。Go語言是沒有引用傳遞的,在C++中,函數參數的傳遞方式有引用傳遞。
————————————————
版權聲明:本文為CSDN博主「走,我們去吹風」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_51991615/article/details/130345352
首先明確幾個點:
- 1、官方明確表明:Go中沒有引用類型,鏈接在這
- 2、官方明確表明:Go中function所有參數的傳遞都是值傳遞,鏈接在這
- 3、Golang預設是值傳遞,即拷貝傳遞;
- 4、有些值頭部head中含有地址,如(切片,map類型),所以導致看起來像是引用傳遞
那麼問題來了,既然Go沒有引用類型的說法,且function的參數都是值傳遞,為什麼當我使用切片slice或者map等類型作為參數時,有傳引用的錯覺呢?
/**
* 測試切片不是引用傳遞
*/
func TestPassByValue(t *testing.T) {
sli := []int{0, 1, 2, 3, 4}
fmt.Printf("sli的地址:%p\n", unsafe.Pointer(&sli))
fmt.Printf("sli[0]的地址:%p\n", unsafe.Pointer(&sli[0]))
//unsafe.Pointer(&sli[0])是一個指針不假,但它也僅僅是切片結構內包含的一個值
t.Log(sli)
modifySlice(sli)
t.Log(sli)
}
func modifySlice(s []int) {
//slice的底層大概如下:
type slice struct {
array unsafe.Pointer // 就是這裡的unsafe.Pointer(&s[0]),因為是值傳遞,所以這個指針是跟外面一樣的
len int
cap int
}
fmt.Printf("參數的地址:%p\n", unsafe.Pointer(&s))
fmt.Printf("參數[0]的地址: %p \n", unsafe.Pointer(&s[0]))
s[0] = 111 //此時直接修改參數的值,外面的值也跟著同步修改
s[1] = 222 //但當你進行append操作或者二倍擴容時,&s[0]的地址就會改變,數外的切片就不會跟著改變了。
}
總結:
之所以有傳引用的錯覺是因為slice本質是一個結構體,結構體內有個指針值,而這個值指向切片的第一個元素,因為是值傳遞,所以slice內的這個指針跟函數外邊是一樣的,此時,你在函數內修改切片的某個值,函數外會跟著改變。 但當你進行append操作或二倍擴容時,這個指針值就會改變,此時,你再次在函數內對切片進行修改,函數外不會跟著改變。