详解go语言的array和slice 【二】
上一篇 ?詳解go語言的array和slice 【一】已經(jīng)講解過,array和slice的一些基本用法,使用array和slice時(shí)需要注意的地方,特別是slice需要注意的地方比較多。上一篇的最后講解到創(chuàng)建新的slice時(shí)使用第三個(gè)索引來限制slice的容量,在操作新slice時(shí),如果新slice的容量大于長度時(shí),添加新元素依然后使源的相應(yīng)元素改變。這一篇里我會(huì)講解到如何避免這些問題,以及迭代、和做為方法參數(shù)方面的知識(shí)點(diǎn)。
slice的長度和容量設(shè)置為同一個(gè)值
如果在創(chuàng)建新的slice時(shí)我們把他的長度和容量的值設(shè)置為樣的值,那么在append新元素時(shí),底層會(huì)創(chuàng)建一個(gè)新的array并把之前的值復(fù)制過去。這樣就不會(huì)影響之前共同的底層array了。
// 創(chuàng)建一個(gè)容量和長度均為6的sliceslice1 := []int{5, 23, 10, 2, 61, 33}// 對(duì)slices1進(jìn)行切片,長度為2容量為3slice2 := slice1[1:3:3]fmt.Println("cap", cap(slice2))fmt.Println("slice2", slice2)//修改一個(gè)共同指向的元素//兩個(gè)slice的值都會(huì)修改slice2[0] = 11111fmt.Println("slice1", slice1)fmt.Println("slice2", slice2)// 增加一個(gè)元素slice2 = append(slice2, 55555)fmt.Println("slice1: ", slice1)fmt.Println("slice2: ", slice2)輸出結(jié)果
cap 2 slice2 [23 10] slice1 [5 11111 10 2 61 33] slice2 [11111 10] slice1: [5 11111 10 2 61 33] slice2: [11111 10 55555]代碼中的長度和容量是一樣的,長度和容量的計(jì)算公式看我的上一篇博客。增加一個(gè)元素后,原來共同指向的底層數(shù)據(jù)是沒有變的。因?yàn)閟lice2的底層array被重新賦值了。
迭代slice
go語言內(nèi)置一個(gè)關(guān)鍵字range用于迭代集合,當(dāng)然他也可以迭代slice,也可以使用? _? 來忽略我們不關(guān)心的元素,但是如果只關(guān)心index則不需這么寫 for index,_ := range slice1。下在給出完整代碼
// 創(chuàng)建一個(gè)容量和長度均為6的sliceslice1 := []int{5, 23, 10, 2, 61, 33}for index, value := range slice1 {fmt.Println("index: ", index, " value: ", value)}// 可以忽略我們不關(guān)心的元素// 只關(guān)心valuefor _, value := range slice1 {fmt.Println("value ", value)}// 只關(guān)心index, 可以不用 _for index := range slice1 {fmt.Println("index: ", index)}?
? 需要注意的是rang 迭代的value值并是一個(gè)復(fù)本,我們可以對(duì)比一下迭代的value和原slice內(nèi)相應(yīng)index下value的地址:
// 創(chuàng)建一個(gè)容量和長度均為6的sliceslice1 := []int{5, 23, 10, 2, 61, 33}for index, value := range slice1 {fmt.Println("index: ", index, " value address : ", &value, " slice1 value address", &slice1[index])}輸出結(jié)果
index: 0 value address : 0xc04204e088 slice1 value address 0xc04206a030 index: 1 value address : 0xc04204e088 slice1 value address 0xc04206a038 index: 2 value address : 0xc04204e088 slice1 value address 0xc04206a040 index: 3 value address : 0xc04204e088 slice1 value address 0xc04206a048 index: 4 value address : 0xc04204e088 slice1 value address 0xc04206a050 index: 5 value address : 0xc04204e088 slice1 value address 0xc04206a058slice1中value的地址是不斷變化的。而迭代的value值的地址沒有變化,這是因?yàn)関alue是一個(gè)變量,為次迭代的時(shí)候賦不同的值。我們把代碼寫成下面這樣,你就清楚了
var index, value intfor index, value = range slice1 {fmt.Println("index: ", index, &index, " value address : ", &value, " slice1 value address", &slice1[index])}? 除了使用rang 也可以使用傳統(tǒng)的for循環(huán)來做迭代
slice1 := []int{5, 23, 10, 2, 61, 33}for i, len := 1, len(slice1); i < len; i++ {fmt.Println("index: ", i, " value:", slice1[i])}?
?slice作為方法參數(shù)
? 由于slice的特殊結(jié)構(gòu),有一個(gè)指針指向一個(gè)數(shù)組
s := make([]int, 2, 5)fmt.Println("len: ", len(s))fmt.Println("cap: ", cap(s))s = append(s, 2)s[0] = 12?
所以,slice做為方法的參數(shù)傳遞時(shí),只會(huì)復(fù)制slice本身而不會(huì)復(fù)制slice底層的array.如果我們創(chuàng)建一個(gè)int類型有100萬長度的slice ,把他傳遞給一個(gè)方法時(shí),只需要復(fù)制24個(gè)字節(jié)就夠了。指針需要8個(gè),長度和容量都是8個(gè)。
const size int = 1000 * 1000func main() {slice0 := make([]int, size)fmt.Println("slice0 len: ", len(slice0), " cap :", cap(slice0))doSomeThing(slice0) }func doSomeThing(s []int) {fmt.Println(len(s)) }?
?
轉(zhuǎn)載于:https://www.cnblogs.com/li-peng/p/7541554.html
總結(jié)
以上是生活随笔為你收集整理的详解go语言的array和slice 【二】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转载】周鸿祎:做产品体验先把自己切换到
- 下一篇: vb2010 java,连接用vb成功连