2016-11-23 99 views
3

我想探索一些關於如何在複製變量時分配內存的問題。我做了一些測試,這一次讓我困惑:複製變量時的數組地址

func testArrayAddress() { 
    var a [3]int 
    b := a 
    fmt.Printf("address of a %p and of b %p \n", &(a[0]), &(b[0])) 
} 

輸出是:

address of a 0xc8200126e0 and of b 0xc820012700 

然而,由於我假設A和B指向同一個數組所以第一個元素的起始地址應是相同的?

這讓我懷疑當我們執行語句b := a時發生了什麼?最初我以爲它會只爲數組分配一個內存塊,當我們初始化變量ab := a使b指向相同的內存位置,但它不能解釋爲什麼第一個元素的地址不相同(應該是相同的元素)。

我改的第一行代碼:

func testArrayAddress() { 
    var a = []int{1, 2, 3} 
    b := a 
    fmt.Printf("address of a's first element %p and of b %p \n", &(a[0]), &(b[0])) 
} 

然後輸出爲:

address of a's first element 0xc8200126e0 and of b 0xc8200126e0 

現在給了我同樣的結果。

我想問的問題是:

  1. 在Golang當我們做變量副本(b := a),難道我們也創建數據在內存中的副本?這對於不可變和可變類型都是一樣的嗎?

  2. 如果我們也在複製可變類型(例如數組),那麼它如何設法實現修改變量也會影響到其他(a[0] = 42會影響b[0])?

  3. []int類型與[number]int類型有什麼不同?我在最後一種情況下測試過的類型是什麼?

+2

在Tour of Go(https://tour.golang.org)和有關數組的博客文章中,這些都很好解釋https://blog.golang.org/slices and slices https:// blog .golang.org /去切片使用率和-內部。簡短的回答:'b:= a'總是複製。 Go中沒有不可變的類型。 2)與數組無關,這是切片的用途。 3)'[] int'是一個片段,'[3] int'是一個數組。請仔細閱讀https://tour.golang.org/moretypes/6和followig幻燈片。 – Volker

回答

5

[3]intarray[]intslice

數組意味着它的所有元素,當傳遞它或分配它時,它的所有元素都被複制。

切片是指向底層數組的連續部分的小型結構類描述符。當傳遞或分配時,只會複製此頭(包括指針),因此「新」片將指向相同的後備數組。

要回答你的問題的確切:

  1. 是,b := a副本的所有元素,如果a是一個數組,但前提是a頭是一個切片。只要只有1個goroutine訪問(修改)a,並且如果多個goroutine可以修改它們,那麼這兩個都是安全的。

  2. 如果一個數組被複制,它將完全獨立於「原始」,修改該副本對原始數據沒有影響。如果複製切片,副本將指向存儲元素的同一個後備數組。如果通過複製片修改元素,則修改單個元素,然後通過原始片檢查它,只檢查元素的唯一「實例」(並觀察修改後的值)。

  3. 這是在第一句話:[]int是一個切片,[n]int是一個數組。

查看相關問題:

Why have arrays in Go?
Golang passing arrays to the function and modifying it

閱讀更多詳情,以下博客文章在片和數組:

Go Slices: usage and internals
Arrays, slices (and strings): The mechanics of 'append'