關於slice分配內存

slice是golang提供的一個很好的符合類型。既支持數據動態擴展,又能隨機訪問,使數據保持很好的局部性。但是slice有一個性能可能導致數據的一致性和預期不一致,就是它會按需爲slice收集內存。參考這段代碼:

=========================================

package main


import "fmt"


func main() {
var data = []string{"one", "", "three"}     //what's the differenct to assign underlying or not
var data2 = [...]string{"one", "", "three"} //what's the differenct to assign underlying or not
intTest := 3
fmt.Printf("intTest %%T after append is %T \n", intTest)
fmt.Printf("intTest %%p after append is %p \n", intTest)
fmt.Printf("data %%v is %v \n", data)
fmt.Printf("data %%q is %q \n", data)
out := data[:0]
for _, s := range data {
if s != "" {
out = append(out, s)
}
}
fmt.Printf("data %%v after append is %v \n", data)
fmt.Printf("data %%q after append is %q \n", data)
fmt.Printf("data %%s after append is %s \n", data)
fmt.Printf("data %%T after append is %T \n", data)
fmt.Printf("data %%p after append is %p \n", data)
fmt.Printf("&data %%p after append is %p \n", &data)
fmt.Printf("data2 %%T after append is %T \n", data2)
fmt.Printf("data2 %%p after append is %p \n", data2)
fmt.Printf("&data2 %%p after append is %p \n", &data2)
fmt.Printf("&data2 %%d after append is %d \n", &data2)


fmt.Printf("out %%v after append is %v \n", out)
fmt.Printf("out %%q after append is %q \n", out)


out2 := append(data[:0], "a", "b", "c", "d")
fmt.Printf("data %%v after append is %v \n", data)
fmt.Printf("data %%q after append is %q \n", data)
fmt.Printf("out2 %%v after append is %v \n", out2)
fmt.Printf("out2 %%q after append is %q \n", out2)


out3 := append(data[:0], "a", "b", "c")
fmt.Printf("data %%v after append is %v \n", data)
fmt.Printf("data %%q after append is %q \n", data)
fmt.Printf("out3 %%v after append is %v \n", out3)
fmt.Printf("out3 %%q after append is %q \n", out3)
}

=========================================

output:

=========================================

  1. intTest %T after append is int
  2. intTest %p after append is %!p(int=3)
  3. data %v is [one  three]
  4. data %q is ["one" "" "three"]
  5. data %v after append is [one three three]
  6. data %q after append is ["one" "three" "three"]
  7. data %s after append is [one three three]
  8. data %T after append is []string
  9. data %p after append is 0xc420062150
  10. &data %p after append is 0xc42007a020
  11. data2 %T after append is [3]string
  12. data2 %p after append is %!p([3]string=[one  three])
  13. &data2 %p after append is 0xc420062180
  14. &data2 %d after append is &[%!d(string=one) %!d(string=) %!d(string=three)]
  15. out %v after append is [one three]
  16. out %q after append is ["one" "three"]
  17. data %v after append is [one three three]
  18. data %q after append is ["one" "three" "three"]
  19. out2 %v after append is [a b c d]
  20. out2 %q after append is ["a" "b" "c" "d"]
  21. data %v after append is [a b c]
  22. data %q after append is ["a" "b" "c"]
  23. out3 %v after append is [a b c]
  24. out3 %q after append is ["a" "b" "c"]

=========================================


從輸出裏我們可以得出兩條結論:

1. 對比第17行(append數據長度超出capacity)和第21行的輸出(append數據長度未超出capacity),slice在容量足夠的時候修改已有的array,在容量不夠的時候才realloc內存基於新的內存建立array

2. 對比第12行和9行,golang是強類型的,%p只對引用內型或者取地址有效

3. 對比第9行和第10行,golang對slice和&slice的值定義了不同的語義



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章