函數定義:func append(slice []Type, elems ...Type) []Type
函數說明:內建函數append追加一個或多個elems到一個slice依賴的array的末尾,若是這個slice有足夠的capacity,則reslice以容納新增元素;若是capacity空間不夠,則從新分配內存保存新的slice依賴的array,函數返回更新後的slice.(slice是引用,array保存真正的數據,slice切片理解:https://blog.haohtml.com/arch... )html
注意:append不會修改傳參進來的slice(len和cap),只會在不夠用的時候新分配一個array,並把以前的slice依賴的array數據拷貝過來;因此對同一個slice 重複 append,只要不超過cap,都是修改的同一個array,後面的會覆蓋前面golang
圖片裏提到"Capacity grows in a way not related to the size of appending data",那麼,增加算法是什麼樣的呢?看源代碼 src/runtime/slice.go:算法
newcap := old.cap doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { if old.len < 1024 { newcap = doublecap } else { // Check 0 < newcap to detect overflow // and prevent an infinite loop. for 0 < newcap && newcap < cap { newcap += newcap / 4 } // Set newcap to the requested cap when // the newcap calculation overflowed. if newcap <= 0 { newcap = cap } } }
代碼後面還會對newcap進行roundup,好比在64位平臺,newcap是奇數的話就會+1app
package main import ( "fmt" ) func main(){ a := []int{1,2} b := append(a,3) fmt.Printf("cap(a)=%v,cap(b)=%v\n",cap(a),cap(b)) c := append(b,4) d := append(b,5) fmt.Printf("cap(a)=%v,cap(b)=%v\n",cap(a),cap(b)) fmt.Println(a,b,c,d) fmt.Printf("%p,%p,%p,%p\n",a,b,c,d) }
第一次append,超出了a的cap範圍,分配一個新的newcap爲oldcap*2的array,即4;a不變
第二次append,len(b)是3,cap(b)是4,沒有超出b的cap範圍,b所依賴的array在len(b)的位置追加4,c共用這個array;b不變
第三次append,因爲b沒有變化,b所依賴的array在len(b)的位置追加5,會覆蓋上一步的4
因此:c[3]和d[3]引用的是同一塊內存,都是5函數
另外,若是 d:= append(c,5)
則結果就是 c[3]=4,d[3]=4,d[4]=5由於這一步會新分配array,並將c的數據拷貝過來oop
寫得比較匆忙,若有紕漏,歡迎指正。spa