一 數組簡介:
數組是內置(build-in)類型,是一組同類型數據的集合,它是值類型,通過從0開始的下標索引訪問元素值。在初始化后長度是固定的,無法修改其長度。當作為方法的參數傳入時將復制一份數組而不是引用同一指針。數組的長度也是其類型的一部分,通過內置函數len(array)獲取其長度。
注意:和C中的數組相比,又是有一些不同的
1. Go中的數組是值類型,換句話說,如果你將一個數組賦值給另外一個數組,那么,實際上就是將整個數組拷貝一份
2. 如果Go中的數組作為函數的參數,那么實際傳遞的參數是一份數組的拷貝,而不是數組的指針。這個和C要區分開。因此,在Go中如果將數組作為函數的參數傳遞的話,那效率就肯定沒有傳遞指針高了。
3. array的長度也是Type的一部分,這樣就說明[10]int和[20]int是不一樣的。
二 數組初始化
初始化數組的初始化有多種形式,查看示例代碼 [5] int {1,2,3,4,5}
長度為5的數組,其元素值依次為:1,2,3,4,5
[5] int {1,2}
長度為5的數組,其元素值依次為:1,2,0,0,0 。在初始化時沒有指定初值的元素將會賦值為其元素類型int的默認值0,string的默認值是""
[...] int {1,2,3,4,5}
長度為5的數組,其長度是根據初始化時指定的元素個數決定的
[5] int { 2:1,3:2,4:3}
長度為5的數組,key:value,其元素值依次為:0,0,1,2,3。在初始化時指定了2,3,4索引中對應的值:1,2,3
[...] int {2:1,4:3}
長度為5的數組,起元素值依次為:0,0,1,0,3。由於指定了最大索引4對應的值3,根據初始化的元素個數確定其長度為5賦值與使用
三 數組的訪問
數組通過下標訪問元素,可修改其元素值
<code>arr :=[...] int{1,2,3,4,5}
arr[4]=arr[1]+len(arr) //arr[4]=2+5
</code>
通過for遍歷數組元素
數組是值類型,將一個數組賦值給另一個數組時將復制一份新的元素
<code>arr2 := [5]int{1,2}
arr5 := arr2
arr5[0] = 5
arr2[4] = 2
fmt.Printf(" arr5= %d \n arr2=%d \n arr5[0]==arr2[0]= %s \n", arr5, arr2, arr5[0] == arr2[0])
OutPut:
arr5=[5200 0]
arr2=[1200 2]
arr5[0]==arr2[0]=false</code>
四 切片簡介
數組的長度不可改變,在特定場景中這樣的集合就不太適用,Go中提供了一種靈活,功能強悍的內置類型Slices切片(“動態數組"),與數組相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。切片中有兩個概念:一是len長度,二是cap容量,長度是指已經被賦過值的最大下標+1,可通過內置函數len()獲得。容量是指切片目前可容納的最多元素個數,可通過內置函數cap()獲得。切片是引用類型,因此在當傳遞切片時將引用同一指針,修改值將會影響其他的對象。
五 切片的初始化
切片可以通過數組來初始化,也可以通過內置函數make()初始化 .初始化時len=cap,在追加元素時如果容量cap不足時將按len的2倍擴容
s :=[] int {1,2,3 }
直接初始化切片,[]表示是切片類型,{1,2,3}初始化值依次是1,2,3.其cap=len=3
s := arr[:]
初始化切片s,是數組arr的引用
s := arr[startIndex:endIndex]
將arr中從下標startIndex到endIndex-1 下的元素創建為一個新的切片
s := arr[startIndex:]
缺省endIndex時將表示一直到arr的最后一個元素
s := arr[:endIndex]
缺省startIndex時將表示從arr的第一個元素開始
s1 := s[startIndex:endIndex]
通過切片s初始化切片s1
s :=make([]int,len,cap)
通過內置函數make()初始化切片s,[]int 標識為其元素類型為int的切片
slice可以從一個數組或一個已經存在的slice中再次聲明。slice通過array[i:j]來獲取,其中i是數組的開始位置,j是結束位置,但不包含array[j],它的長度是j-i。
注意slice
和數組在聲明時的區別:
聲明數組時,方括號內寫明了數組的長度或使用...
自動計算長度,而聲明slice
時,方括號內沒有任何字符。
結構區別:

六 賦值和使用
-
切片是引用類型,在使用時需要注意其操作。查看示例代碼 ,在線運行示例代碼 切片可以通過內置函數append(slice []Type,elems ...Type)追加元素,elems可以是一排type類型的數據,也可以是slice,因為追加的一個一個的元素,因此如果將一個slice追加到另一個slice中需要帶上"...",這樣才能表示是將slice中的元素依次追加到另一個slice中。另外在通過下標訪問元素時下標不能超過len大小,如同數組的下標不能超出len范圍一樣。
- s :=append(s,1,2,3,4)
- s :=append(s,s1...)
slice
的默認開始位置是0,ar[:n]
等價於ar[0:n]
slice
的第二個序列默認是數組的長度,ar[n:]
等價於ar[n:len(ar)]
- 如果從一個數組里面直接獲取
slice
,可以這樣ar[:]
,因為默認第一個序列是0,第二個是數組的長度,即等價於ar[0:len(ar)]
下面這個例子展示了更多關於slice
的操作:
<code>// 聲明一個數組
var array = [10]byte{'a','b','c','d','e','f','g','h','i','j'}
// 聲明兩個slice
var aSlice, bSlice []byte
// 演示一些簡便操作
aSlice = array[:3]// 等價於aSlice = array[0:3] aSlice包含元素: a,b,c
aSlice = array[5:]// 等價於aSlice = array[5:10] aSlice包含元素: f,g,h,i,j
aSlice = array[:] // 等價於aSlice = array[0:10] 這樣aSlice包含了全部的元素
// 從slice中獲取slice
aSlice = array[3:7] // aSlice包含元素: d,e,f,g,len=4,cap=7
bSlice = aSlice[1:3]// bSlice 包含aSlice[1], aSlice[2] 也就是含有: e,f
bSlice = aSlice[:3] // bSlice 包含 aSlice[0], aSlice[1], aSlice[2] 也就是含有: d,e,f
bSlice = aSlice[0:5]// 對slice的slice可以在cap范圍內擴展,此時bSlice包含:d,e,f,g,h
bSlice = aSlice[:] // bSlice包含所有aSlice的元素: d,e,f,g
</code>
slice
是引用類型,所以當引用改變其中元素的值時,其它的所有引用都會改變該值,例如上面的aSlice
和bSlice
,如果修改了aSlice
中元素的值,那么bSlice
相對應的值也會改變。
從概念上面來說slice
像一個結構體,這個結構體包含了三個元素:
- 一個指針,指向數組中
slice
指定的開始位置
- 長度,即
slice
的長度
- 容量:(cap)
<code>Array_a := [10]byte{'a','b','c','d','e','f','g','h','i','j'}
Slice_a := Array_a[2:5]
</code>
上面代碼的真正存儲結構如下圖所示
