1. 程式人生 > >你可能不知道的golang知識點

你可能不知道的golang知識點

讀書筆記式,持續更新中...

陣列切片

如何計算長度和容量

函式 append 會智慧地處理底層陣列的容量增長。在切片的容量小於 1000 個元素時,總是會成倍地增加容量。一旦元素個數超過 1000,容量的增長因子會設為 1.25,也就是會每次增加 25%的容量。隨著語言的演化,這種增長演算法可能會有所改變。

設定長度和容量一樣的好處

內建函式 append 會首先使用可用容量。一旦沒有可用容量,會分配一個新的底層陣列。這導致很容易忘記切片間正在共享同一個底層陣列。一旦發生這種情況,對切片
進行修改,很可能會導致隨機且奇怪的問題。對切片內容的修改會影響多個切片,卻很難找到問題的原因。

如果在建立切片時設定切片的容量和長度一樣,就可以強制讓新切片的第一個 append 操作建立新的底層陣列,與原有的底層陣列分離。新切片與原有的底層陣列分離後,可以安全地進行後續修改。

// 其長度和容量都是 5 個元素
source := []string{"Apple", "Orange", "Plum", "Banana", "Grape"}
// 對第三個元素做切片,並限制容量
// 其長度和容量都是 1 個元素
slice := source[2 : 4: 4]
// 向 slice 追加新字串
slice = append(slice, "Kiwi")
fmt.Println(source) // [Apple Orange Plum Banana Grape]
fmt.Println(slice) // [Plum Banana Kiwi]

range

range 建立了每個元素的副本,而不是直接返回對該元素的引用

// 建立一個整型切片
// 其長度和容量都是 4 個元素
slice := []int{10, 20, 30, 40}
// 迭代每個元素,並顯示值和地址
for index, value := range slice {
    fmt.Printf("Value: %d Value-Addr: %X ElemAddr: %X\n",
        value, &value, &slice[index])
}

結果為

Value: 10 Value-Addr: C4200180A8 ElemAddr: C420014200
Value: 20 Value-Addr: C4200180A8 ElemAddr: C420014208
Value: 30 Value-Addr: C4200180A8 ElemAddr: C420014210
Value: 40 Value-Addr: C4200180A8 ElemAddr: C420014218

因為迭代返回的變數是一個迭代過程中根據切片依次賦值的新變數,所以 value 的地址總
是相同的。要想獲取每個元素的地址,可以使用切片變數和索引值。

在函式間傳遞切片

在 64 位架構的機器上,一個切片需要 24 位元組的記憶體:指標欄位需要 8位元組,長度和容量欄位分別需要 8位元組。由於與切片關聯的資料包含在底層數組裡,不屬於切片本身,所以將切片複製到任意函式的時候,對底層陣列大小都不會有影響。複製時只會複製切片本身,不會涉及底層陣列。