極客兔兔部落格筆記-GO語言高效能程式設計-常用資料結構
參考部落格:極客兔兔
字串拼接方法的比較
- strings.Builder和+
func builderConcat(n int,str string) string {
var builder strings.Builder
for i := 0;i<n;i++{
builder.WriteString(str)
}
return builder.String()
}
當時用+拼接2個字串時候是開闢一段新的空間。而strings.Builder,bytes.Buffer,包括切片的[]byte的記憶體是以倍數申請的。當一萬個字串拼接時,strings.Builder方法的記憶體消耗大概是+的記憶體消耗的千分之一。
slice的效能及陷阱
當silce的容量較小時記憶體是以2的倍數擴大的,當達到2048時採用新的策略,避免記憶體申請過大,導致浪費。
切片的結構:
struct {
ptr *[]T
len int
cap int
}
效能缺陷:在已有切片的基礎上進行切片,不會建立新的底層陣列,因為原來的底層資料沒有發生變化,記憶體會一直佔用,直到沒有變數引用該陣列。推薦:用copy
代替re-slice //[x:x]
。
當copy時,切片建立一個新的底層切片,當原切片的底層陣列沒有引用時記憶體就會被GC。
for和range的效能比較
range可以很方便地去遍歷陣列、切片、字典和通道。對nil型別,迭代次數為0。對於通道,for迴圈迭代直到通道被關閉。
僅遍歷下標時for和range效能幾乎一樣,同時遍歷下標和值,for的效能大約是range的2000倍。
range 在迭代過程中返回的是迭代值的拷貝,如果每次迭代的元素的記憶體佔用很低,那麼 for 和 range 的效能幾乎是一樣,例如 []int
。但是如果迭代的元素記憶體佔用較高,例如一個包含很多屬性的 struct 結構體,那麼 for 的效能將顯著地高於 range,有時候甚至會有上千倍的效能差異。對於這種場景,建議使用 for,如果使用range,建議只迭代下標,通過下標訪問迭代值,這種使用方式和 for 就沒有區別了。如果想使用 range 同時迭代下標和值,則需要將切片/陣列的元素改為指標,才能不影響效能。
Go空結構體struct{}的使用
unsafe.Sizeof
可以得到一個數據型別例項所需要佔用的位元組數。
空結構體不佔據記憶體空間,因此可以廣泛作為各種場景下面的佔位符。
有時候使用 channel 不需要傳送任何的資料,只用來通知子協程(goroutine)執行任務,或只用來控制協程併發度。這種情況下,使用空結構體作為佔位符就非常合適了。