go語言slice的理解

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Golang slice

 

 yongsean  作者

2017.02.17 00:07  開啟App

建立切片,len、cap、append

 

b := make([]int, 5)

println(len(b), cap(b)) // 輸出結果是:5, 5

 

fmt.Println(b) // 輸出結果是:[0 0 0 0 0]

上述代碼是產生預設佔用5個0值的切片,下面的輸出結果是另一回事

 

b := make([]int, 0, 5)

println(len(b), cap(b)) // 輸出結果是:0, 5

 

fmt.Println(b) // 輸出結果是:[]

上述代碼是產生cap長度為5,實際使用長度為0的切片,在指定的cap內進行append操作,是不會發生記憶體拷貝擴容操作。

 

b := make([]int, 0, 2)

fmt.Printf("%d, %d, %p\n", len(b), cap(b), b) // 0, 2, 0xc420012190

 

b = append(b, 1)

b = append(b, 2)

fmt.Printf("%d, %d, %p\n", len(b), cap(b), b) // 2, 2, 0xc420012190

 

b = append(b, 3)

fmt.Printf("%d, %d, %p\n", len(b), cap(b), b) // 3, 4, 0xc420012198

最後一行輸出顯示,記憶體位址跟前2次輸出的不一樣,並且cap值也在原來的基礎上,翻了一倍,相當於做了如下操作:

 

// mock append

tmp := make([]int, 0, cap(b) * 2) // 是當前的cap值的翻倍

// 複製操作略過。。。

b = tmp

copy

 

正常的切片copy操作

 

a := make([]int, 5)

a[0] = 1

a[1] = 2

fmt.Println(a) // [1 2 0 0 0]

 

b := make([]int, 5)

b[0] = 11

b[1] = 22

b[2] = 33

b[3] = 44

b[4] = 55

fmt.Println(b) // [11 22 33 44 55]

 

copy(b, a)

fmt.Println(b) // [1 2 0 0 0]

另一個效果

 

a := make([]int, 5)

a[0] = 1

a[1] = 2

fmt.Println(a) // [1 2 0 0 0]

 

b := make([]int, 0, 5) // len(b)!=cap(b)

b = append(b, 11)

b = append(b, 22)

fmt.Println(b) // [11, 22]

 

copy(b, a)

fmt.Println(b) // [1 2]

第三行的輸出,只是[1 2],不是[1 2 0 0 0],是對b切片裡len(b)長度內的元素進行對應下標複製操作,假如len(b)==0,那輸出結果是[]。 這是需要小心的地方,老司機會一不留神搞錯,不瞭解的人那就更難說。

 

切片的切片

 

a := make([]int, 5)

a[0] = 1

a[1] = 2

a[2] = 3

a[3] = 4

a[4] = 5

// 未經處理資料輸出

fmt.Printf("%v, %p\n", a, a) // [1 2 3 4 5], 0xc4200141b0

 

aslice1 := a[1:]

// 第一組輸出

fmt.Printf("%v, %p\n", aslice1, aslice1) // [2 3 4 5], 0xc4200141b8

fmt.Println(len(aslice1), cap(aslice1)) // 4 4

 

aslice2 := a[1:3]

// 第二組輸出

fmt.Printf("%v, %p\n", aslice2, aslice2) // [2 3], 0xc4200141b8

fmt.Println(len(aslice2), cap(aslice2)) // 2 4

 

aslice3 := a[:3]

// 第三組輸出

fmt.Printf("%v, %p\n", aslice3, aslice3) // [1 2 3], 0xc4200141b0

fmt.Println(len(aslice3), cap(aslice3)) // 3 5

上面幾組輸出,粗看沒什麼,細看還是有值得注意的

 

每組的len和cap值都不太一樣

切片的記憶體位址不是完全相同

len的值好理解,無異議。

 

cap的值:

 

在 第一組輸出 中是4,是新切片首地址到原始切片尾地址的個數。

在 第二組輸出 中也是4,是新切片首地址到原始切片尾地址的個數

在 第三組輸出 中是5,道理如上

記憶體位址:

 

未經處理資料輸出的地址和第三組輸出的地址一樣

第一組輸出的地址和第二組輸出的地址一樣

這樣輸出的原因是,指向的切片首地址一樣。在64位作業系統,int類型佔8個位元組,第二組輸出的地址比第三組輸出的地址多8個數值。若有新的切片是如下定義:

 

aslice4 := a[2:]

fmt.Println("%p\n", aslice4) // 0xc4200141c0

那輸出結果是:0xc4200141c0,是 0xc4200141b8+8 的結果

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.