[Introduction]Go特殊的引用類型:值傳遞/指針傳遞/引用傳遞

結論:golang中函數傳參只有值傳遞html

變量名/變量值/變量地址

var a = 10
log.Printf("%p\n",a) // 變量地址假設爲 0x00000001

變量名a,變量值10,變量地址0x00000001程序員

指針/引用

指針變量存放其餘變量的地址。在C++中引用就是變量的另外一名字golang

變量名自己並無做用,只至關於代號利於程序員編程,引用做爲別名本質上仍是指向同一個內存地址。指針本質上佔用一小段內存空間shell

值傳遞

值傳遞就是深拷貝,在函數內傳遞的副本,並不會影響函數外的實參編程

在函數調用時,將實參深拷貝後壓棧segmentfault

指針傳遞

形參爲指向實參地址的指針,當對形參的指向操做時,就至關於對實參自己進行的操做數組

引用傳遞 for C++

在C++中的引用傳遞本質上將實參的地址傳遞到函數中,和指針傳遞效果相似函數

在Go中的函數調用只有值傳遞,可是存在引用類型slice、map、channelpost

array := []int{1,2,3}
arrayslice := array[:]

GO中「特殊的引用類型」

可以經過make()建立的都是引用類型,比圖slicemapslice本質上是一個指向數組內存空間的一個指針類型:設計

type Slice struct {
    point Point // 內存地址
    len int
    cap int
}

因此本質上對slice切片的賦值,實質上就是對Slice這個結構體進行深拷貝,對於Point來講天然是指向同一段空間了。雖然是值傳遞,可是本質上是兩個Slice對象,傳遞的對象是指針,指針相同,所以算是特殊的值傳遞。map同理

在Golang中的例子能夠比較直觀反應切片特性:

func printAddr(s []int) { // 打印數組地址 值參數
    log.Printf("printAddr:%p\n", &s[0])
}

func printAddrPoint(ps *[]int) { // 打印數組地址 指針參數
    log.Printf("printAddrPoint:%p\n", &((*ps)[0]))
}

func main() {
    array := [3]int{1, 2, 3}   // 數組   commit 1
    // array := []int{1, 2, 3} // 切片   commit 2
    log.Printf("array:%p\n", &array)

    arrayslice := array[:] // 切片
    log.Printf("arrayslice:%p\n", &arrayslice)

    printAddr(arrayslice)
    printAddrPoint(&arrayslice)
}

控制檯輸出:

2020/08/07 15:15:35 array:0xc00000e3c0
2020/08/07 15:15:35 arrayslice:0xc000004620
2020/08/07 15:15:35 printAddr:0xc00000e3c0
2020/08/07 15:15:35 printAddrPoint:0xc00000e3c0

本質上是由於切片傳遞依舊是值傳遞,雖然結構體自己不是一個地址,可是裏面包含的起始地址都是array[0]這也能夠解釋爲何三者相同

註釋掉commit1,解註釋掉commit2,再次運行結果以下:

2020/08/07 15:22:42 array:0xc0000044a0
2020/08/07 15:22:42 arrayslice:0xc000004640
2020/08/07 15:22:42 printAddr:0xc00000e3c0
2020/08/07 15:22:42 printAddrPoint:0xc00000e3c0

猜想array[0]的地址不出意外也應該是0xc00000e3c0,驗證:

func main() {
    array := []int{1, 2, 3} // 數組
    log.Printf("array[0]:%p\n", &array[0])
}

控制檯輸出:

2020/08/07 15:37:19 array[0]:0xc00000e3c0

arrayarray[0]的地址不一致。array[0]和其餘切片的第零個元素的地址同樣,繼續嘗試後能夠得出結論:

1.數組地址等同於數組首元素地址,和C是一致的

2.切片(結構體)的地址和切片首元素的地址是不一致的,猜想聲明切片的時候順序是先建立了數組,而後初始化切片結構體爲數組引用?

參考連接

Go語言參數傳遞是傳值仍是傳引用

我對變量產生了這些想法

Golang中函數傳參存在引用傳遞嗎?

理解 Golang 中 slice 的底層設計

相關文章
相關標籤/搜索