2022年11月25日 星期五

Golang slice 研究筆記

以前有研究過 Go silce 的指針,後來看了一些文章,才知道說 Go 本身在底層還有一個 array 來處理 slice。


簡單說,我今天建立一個 slice,實際上同時建立了一個 array

而array 實際上就是個指針


所以執行以下 code 會 print 出同樣的值


arr1 := []int{1, 2, 3}
arr2 := arr1

fmt.Printf("%p\n", &arr1[2])
fmt.Printf("%p\n", &arr2[2])

換言之,arr1[1] = 10 同時會更改到 arr2[1],因為兩者底層的 array 是同一個。

這裡提一個有趣的狀況,同樣 arr2 := arr1,但 arr1 有藉由調整過大小:

arr1 := []int{1, 2, 3, 4, 5, 6, 7}
arr2 := arr1

arr1 = append(arr1[0:1], arr1[2:]...)

fmt.Printf("%p\n", &arr1[2])
fmt.Printf("%p\n", &arr2[2])

append(slice []Type, elems ...Type) []Type 會直接更動 slice 底下的 array,而 arr2 和 arr1 對應的 array 又相同,所以兩邊的值都會變更。

但,這段code,如果 print append完後的兩個 array,會發現:

arr1 [1 3 4 5 6 7]
arr2 [1 3 4 5 6 7 7]

再來看這段 code:

arr1 := []int{1, 2, 3, 4, 5, 6, 7}
arr2 := append(arr1[0:2], 10)

fmt.Println("arr1", arr1)
fmt.Println("arr2", arr2)

輸出結果是

arr1 [1 2 10 4 5 6 7]
arr2 [1 2 10]

從上面兩段 code 可以知道,append(slice []Type, elems ...Type) []Type 的動作是

  1. 先去看 slice []Type 對應的 array 以及 slice []Type 的長度
  2. 在該長度後面添值

所以對於 append(arr1[0:2], 10)這段,即是

  1. 找到 slice arr1 對應的 array
  2. 因為 array 的長度超過 3,所以直接更改 array[3]
  3. [ array[0], array[1], array[2], array[3] ] 轉成 slice 存到變數 arr2

參考資料

骏马金龙, (2018, October 26). Go基础系列:Go slice详解. 博客园. https://www.cnblogs.com/f-ck-need-u/p/9854932.html

沒有留言:

張貼留言