Slice又称动态数组,依托数组实现,可以方便的进行扩容、传递等,实际使用中比数组更灵活。想想其它语言必须指定数组长度,总觉得少给了不够用,多给了浪费空间。觉得GO这个动态扩容是个好IDEA,可就是这个扩容让人产生了迷惑。
func AddElement(slice []int, e int) []int {
return append(slice, e)
}
func main() {
var slice1 []int
slice1 = append(slice1,1,2,3)//这里扩容是4(2的倍数,加入的数组项是3个,还剩1位)
newSlice := AddElement(slice1,5) //只加1位,用完上面扩容剩下的
slice1[0] =6 //newSlice[0]与slice1[0]指向相同的地址
fmt.Println(&slice1[0] == &newSlice[0])
fmt.Println(slice1[0],newSlice[0])
}
___go_build_slice_go.exe #gosetup
true
6 6
执行结果是true,两切片指向了相同数组。
然而相同代码,只是多扩容了一个数。
func main() {
var slice1 []int
slice1 = append(slice1,1,2,3,4) //这里扩容是4(2的倍数,加入的数组项也是4个,刚好用完)
newSlice := AddElement(slice1,5)
slice1[0] =6 //newSlice[0]与slice1[0]指向不同的地址,不会修改newSlice[0]指向地址的值
fmt.Println(&slice1[0] == &newSlice[0])
fmt.Println(slice1[0],newSlice[0])
}
___go_build_slice_go.exe #gosetup
false
6 1
两切片指向了不同数组,这是因为上面slice1 扩容后是2的倍数,还有一个空位,恰好AddElement中只增加一个数,没有在AddElement扩容;下面这个没有空位,在AddElement扩容了,返回了个新地址。所以在程序中一定注意这个坑,不要因为扩容增加数组个数不同,而产生数据误差。在程序中多次扩容时,特别是扩容的数组项个数不固定时,一定要注意扩容时产生数组地址,新旧Slice指向数组地址一定弄清楚。