实验一:
我们都知道,数组声明以后,数组的地址和数组内元素的地址是固定的。
而slice则不然,如果修改slice1的元素的值,而不进行append操作,那么slice1[0]的地址会改变吗?

image.png

image.png
也就是说,修改slice的元素的值,元素的地址不变。那么,我们来看看append函数到底干了什么事儿。首先追溯append()函数,然而在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
代码追溯看不到实现,在调试运行中,发现跳转到src\runtime\slice.go的growslice函数,打开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}
}
由此可见,在growslice中,是声明并且初始化了一个新的slice结构体,并且赋值了一个新的unsafe.Pointer地址,原来slice的长度和一个新的容量newcap,所以地址必然改变!