陣列的宣告和初始化
概念
陣列是具有相同 唯一型別 的一組已編號且長度固定的資料項序列(這是一種同構的資料結構);這種型別可以是任意的原始型別例如整型、字串或者自定義型別。陣列長度必須是一個常量表達式,並且必須是一個非負整數。陣列長度也是陣列型別的一部分,所以[5]int和[10]int是屬於不同型別的。陣列的編譯時值初始化是按照陣列順序完成的
陣列元素可以通過 索引(位置)來讀取(或者修改),索引從 0 開始,第一個元素索引為 0,第二個索引為 1,以此類推。(陣列以 0 開始在所有類 C 語言中是相似的)。元素的數目,也稱為長度或者陣列大小必須是固定的並且在宣告該陣列時就給出(編譯時需要知道陣列長度以便分配記憶體);陣列長度最大為 2Gb。
宣告的格式是:
var identifier [len]type
例如:
var arr1 [5]int
每個元素是一個整型值,當宣告陣列時所有的元素都會被自動初始化為預設值 0。
arr1 的長度是 5,索引範圍從 0 到 len(arr1)-1。
第一個元素是 arr1[0],第三個元素是 arr1[2];總體來說索引 i 代表的元素是 arr1[i],最後一個元素是 arr1[len(arr1)-1]。
對索引項為 i 的陣列元素賦值可以這麼操作:arr[i] = value,所以陣列是 可變的。
只有有效的索引可以被使用,當使用等於或者大於 len(arr1) 的索引時:如果編譯器可以檢測到,會給出索引超限的提示資訊;
如果檢測不到的話編譯會通過而執行時會 panic:
runtime error: index out of range
由於索引的存在,遍歷陣列的方法自然就是使用 for 結構:
- 通過 for 初始化陣列項
- 通過 for 列印陣列元素
- 通過 for 依次處理元素
package main
import "fmt"
func main() {
var arr1 [5]int
for i:=0; i < len(arr1); i++ {
arr1[i] = i * 2
}
for i:=0; i < len(arr1); i++ {
fmt.Printf("Array at index %d is %d\n" , i, arr1[i])
}
}
結果
Array at index 0 is 0
Array at index 1 is 2
Array at index 2 is 4
Array at index 3 is 6
Array at index 4 is 8
使用 for-range 的生成方式:
package main
import "fmt"
func main() {
a := [...]string{"a", "b", "c", "d"}
for i := range a {
fmt.Println("Array item", i, "is", a[i])
}
}
結果
Array item 0 is a
Array item 1 is b
Array item 2 is c
Array item 3 is d
Go 語言中的陣列是一種 值型別(不像 C/C++ 中是指向首元素的指標),所以可以通過 new() 來建立: var arr1 = new([5]int)。
那麼這種方式和 var arr2 [5]int 的區別是什麼呢?arr1 的型別是 *[5]int,而 arr2的型別是 [5]int。
這樣的結果就是當把一個數組賦值給另一個時,需要在做一次陣列記憶體的拷貝操作。例如:
arr2 := *arr1
arr2[2] = 100
這樣兩個陣列就有了不同的值,在賦值後修改 arr2 不會對 arr1 生效。
所以在函式中陣列作為引數傳入時,如 func1(arr2),會產生一次陣列拷貝,func1 方法不會修改原始的陣列 arr2。
如果你想修改原陣列,那麼 arr2 必須通過&操作符以引用方式傳過來,例如 func1(&arr2),下面是一個例子
package main
import "fmt"
func f(a [3]int) { fmt.Println(a) }
func fp(a *[3]int) { fmt.Println(a) }
func main() {
var ar [3]int
f(ar) // passes a copy of ar
fp(&ar) // passes a pointer to ar
}
輸出結果:
[0 0 0]
&[0 0 0]