Golang - 指針與引用

​ Golang有指針 , 那麼一切數據都是值傳遞嗎 ? 都須要用戶進行指針傳遞嗎, 其實否則, 對於Go語言, 雖然有指針, 可是其也有引用傳遞. 是否是很繞, 由於引用傳遞就是指針傳遞哇 . 咱們繼續解釋.php

概念

在Go語言中,對於布爾變量數值類型字符串類型數組 以及struct都是按照值傳遞的:值在傳遞給函數或者方法時會被複制一份,而後方法或函數使用的是複製的這份值,也就不會對原值產生什麼影響。通常狀況下,對於布爾變量或數值類型或字符串類型的按值傳遞是很是廉價的,Go語言編譯器會在傳遞過程當中進行安全優化。html

對於大字符串是這樣,對於數組進行值傳遞也是如此。爲了解決可能產生的巨大代價,Go語言使用數組切片來代替數組的使用。傳遞一個切片的代價跟傳遞字符串差很少,不管該切片的長度或容量是多大。對切片進行復制修改操做也不會像字符串那樣須要建立新的切片,由於切片是可變的,屬於引用類型java

所以如下就是重點 :數組

語言中的值傳遞類型有:基本數據類型,數組 , struct安全

特色:變量直接存儲值,內存一般在棧中分配,棧在函數調用完會被釋放 , 在調用函數時將實際參數複製一份傳遞到函數中,這樣在函數中若是對參數進行修改,將不會影響到實際參數 , 因此他最大的好處就是不怕多線程安全性問題. 可是浪費內存多線程

Go語言中的引用類型有:映射(map),數組切片(slice),通道(chan),接口(interface) 與 函數(func)。函數

他的變量默認就是指針變量, 因此不須要作&取地址. 你要是花裏胡哨我也無語.優化

特色:變量存儲的是一個地址,這個地址存儲最終的值。內存一般在堆上分配,經過GC回收。所謂引用傳遞是指在調用函數時將實際參數的地址傳遞到函數中,那麼在函數中對參數所進行的修改,將影響到實際參數。引用註定多個線程中共享一個, 容易出現多線程問題,線程

就以引用傳遞和值傳遞區分 , 切記別被下面帶繞了,這種話分析層面不一樣就不同指針

其實在go語言中,只存在值傳遞,本質上,咱們能夠理解函數的傳遞都是值傳遞,只不過引用類型傳遞的是一個指向底層數據的指針,因此咱們在操做的時候,能夠修改共享的底層數據的值,進而影響到全部引用到這個共享底層數據的變量。

兩大操做符

操做符& : 是返回該變量的內存地址。
操做符* :是返回該指針指向的變量的值,其實就是解除變量的指針引用,返回該變量的值.

空指針 :

當一個指針被定義後沒有分配到任何變量時,它的值爲 nil。
nil 指針也稱爲空指針。
nil在概念上和其它語言的null、None、nil、NULL同樣,都指代零值或空值。

認識指針

指針這個玩意, Java裏沒有,其實Java裏確實有指針,咱們無時無刻在使用,下面我舉一個例子

type People struct {
    name string
    sex  string
    age  int
}

func main() {
    
    var pp *People

    // 1. 返回一個對象
    person1 := People{"zhangsan", "man", 25}

    fmt.Println(person1)

    pp=&person1

    // 2. 直接實例化一個空對象 , 返回一個指針對象
    person2 := new(People)

    //
    pp=person2
    fmt.Println(*pp)

    // 2.返回一個指針對象
    person3 := &People{"wangwu", "man", 25}

    pp=person3

    fmt.Println(*person3)

    fmt.Println(*pp)
}

輸出

{zhangsan man 25}
{  0}
{wangwu man 25}
{wangwu man 25}

這裏告訴你們一個技巧就是 fmt.Println() 輸出中若是首位是 & ,那麼它必定是一個指針類型的數據 . 可是對於默認的引用對象,不必定了,,,

函數傳參是值傳遞 - 可是引用類型是指針傳遞, 不須要用戶寫*申明指針類型

舉個例子 咱們拿數組爲例子 , 舉例指針的用處

func main() {

    // 申明數組類型
    arr := [3]int{1, 2, 3}

    // 原數組
    fmt.Printf("指針 : %p , 數據 : %v\n", &arr,arr)

    // 地址傳遞
    printSlice(&arr)
    
    // 值傳遞
    printSlices(arr)

    // 原數組
    fmt.Printf("指針 : %p , 數據 : %v\n", &arr,arr)

}

func printSlice(arr *[3]int) {
    // 修改數據
    arr[0] = 5
    fmt.Printf("指針 : %p , 數據 : %v\n", arr, *arr)
}
func printSlices(arr [3]int) {
    // 修改數據
    arr[0] = 4
    fmt.Printf("指針 : %p , 數據 : %v\n", &arr, arr)
}

輸出

指針 : 0xc000052140 , 數據 : [1 2 3]
指針 : 0xc000052140 , 數據 : [5 2 3]
指針 : 0xc0000521c0 , 數據 : [4 2 3]
指針 : 0xc000052140 , 數據 : [5 2 3]

參考 http://www.javashuo.com/article/p-dmzlpjku-o.html

相關文章
相關標籤/搜索