實(shí)驗(yàn)一:
我們都知道,數(shù)組聲明以后,數(shù)組的地址和數(shù)組內(nèi)元素的地址是固定的。
而slice則不然,如果修改slice1的元素的值,而不進(jìn)行append操作,那么slice1[0]的地址會(huì)改變嗎?

image.png

image.png
也就是說(shuō),修改slice的元素的值,元素的地址不變。那么,我們來(lái)看看append函數(shù)到底干了什么事兒。首先追溯append()函數(shù),然而在builtin.go中,只有
// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
// slice = append(slice, elem1, elem2)
// slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
// slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type
代碼追溯看不到實(shí)現(xiàn),在調(diào)試運(yùn)行中,發(fā)現(xiàn)跳轉(zhuǎn)到src\runtime\slice.go的growslice函數(shù),打開(kāi)src\runtime\slice.go,
type slice struct {
array unsafe.Pointer
len int
cap int
}
//略...
func growslice(et *_type, old slice, cap int) slice {
//略...
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
for newcap < cap {
newcap += newcap / 4
}
}
}
//略...
var p unsafe.Pointer
//略...
return slice{p, old.len, newcap}
}
由此可見(jiàn),在growslice中,是聲明并且初始化了一個(gè)新的slice結(jié)構(gòu)體,并且賦值了一個(gè)新的unsafe.Pointer地址,原來(lái)slice的長(zhǎng)度和一個(gè)新的容量newcap,所以地址必然改變!