slice中文可以稱為“切片”。是Go語(yǔ)言為處理同類型數(shù)據(jù)序列提供的一個(gè)高效且方便的方式一罩。是在數(shù)組上抽象的一個(gè)數(shù)據(jù)類型杨幼。
切片的使用相當(dāng)?shù)膹V泛。
切片可以直接賦值聂渊,不用提前指定元素的個(gè)數(shù)差购。切片還可以動(dòng)態(tài)的增加元素。
一個(gè)slice也就是切片的聲明是這樣的
s := []int{1,1,2,3,5,8,13,21,34}
也可以使用make創(chuàng)建汉嗽,make創(chuàng)建slice時(shí)需要指定元素個(gè)數(shù)欲逃。
a := make([]int,0)
先指定為0個(gè)
package main
import (
"fmt"
)
func main() {
s := []int{1,1,2,3,5,8,13,21,34}
a := make([]int,0)
fmt.Println(s)
fmt.Println(a)
}
運(yùn)行結(jié)果如下
[1 1 2 3 5 8 13 21 34]
[]
slice添加元素是這樣寫的
a = append(a, 55, 89)
這個(gè)append給slice a添加了2個(gè)整數(shù)。但是诊胞,其實(shí) = 左邊和右邊的a并不是同一個(gè)a了暖夭。
為了驗(yàn)證這兩個(gè)a已經(jīng)發(fā)生了根本的變化锹杈,我們來(lái)取得append前后a的內(nèi)存地址做比較。
不過(guò)迈着,因?yàn)槲覀冎奥暶鱝的時(shí)候竭望,沒(méi)有給a元素個(gè)數(shù),那么它那個(gè)時(shí)候還沒(méi)有分配內(nèi)存裕菠。我們先修改一下
a := make([]int,0)
修改為
a := make([]int,1)
看一下代碼示例
package main
import (
"fmt"
)
func main() {
s := []int{1,1,2,3,5,8,13,21,34}
a := make([]int,1)
fmt.Println(s)
fmt.Println(a)
fmt.Println(&a[0])
a = append(a, 55, 89)
fmt.Println(a)
fmt.Println(&a[0])
}
運(yùn)行的結(jié)果是這樣的
[1 1 2 3 5 8 13 21 34]
[0]
0xc0420361d0
[0 55 89]
0xc04203c480
注意輸出的運(yùn)行結(jié)果中[0 55 89]前后兩個(gè)地址的不同咬清。當(dāng)然,在你的機(jī)器上的地址很可能與我的不同奴潘,那是因?yàn)槊看芜\(yùn)行時(shí)旧烧,環(huán)境不同就可能有不同的內(nèi)存分配過(guò)來(lái)。
既然兩個(gè)a是不同的變量(因?yàn)閍的內(nèi)存地址會(huì)發(fā)生變化画髓,通過(guò)地址訪問(wèn)會(huì)掉入邏輯錯(cuò)誤的坑里)掘剪,那么,下面的代碼就容易理解了奈虾。
b := make([]int, 0)
b = append(a, 144)
fmt.Println(&b[0])
然后你再給 b = append()增加一個(gè)元素看看效果夺谁。然后再減掉剛增加的這個(gè)看看有什么變化。
b := make([]int, 0)
b = append(a, 144, 233)
fmt.Println(&b[0])
是的肉微,看到了b的內(nèi)存地址的變化了匾鸥。這是因?yàn)樵瓉?lái)的slice對(duì)應(yīng)的容量不夠了,隨著slice元素的增加碉纳,又重新分配了內(nèi)存地址勿负。
所以,這里有一個(gè)結(jié)論劳曹,slice在內(nèi)存中保存的位置并不是穩(wěn)定奴愉,沒(méi)什么必要的話,不要用內(nèi)存地址或者指針玩slice铁孵,小心有坑躁劣。