前言
最近剛練習完GoAPI實戰,途中發現自己對Go各種資料型別的理解還是很淺薄,所以打算重新把Go各種資料型別的一些理解做一個整理,同時也分享給大家,初學者,理解淺薄,有不足的歡迎大家指出交流。
陣列的宣告:
陣列的宣告需要指定元素的資料型別,以及儲存元素的數量(陣列長度),如以下程式碼所示
var a [3]int
var b [4]int
a = b //不可以這樣做,因為此時a和b是不同的陣列型別
陣列長度必須是一個非負整數的常量(或常量表示式),陣列長度也是陣列型別的一部分,所以[3]int和[4]int不是同一種型別
陣列需要在宣告時指定陣列長度(編譯時需要知道陣列長度以便分配記憶體),陣列最大長度為2GB。
陣列一旦宣告,它所儲存的資料型別和陣列長度便都不能修改了。如果需要儲存更多的元素,必須先建立一個更長的陣列,然後把原來的陣列裡的值複製到新陣列裡面。
初始化陣列
陣列可以有多種初始化方式,如:
方式1
go 語言在宣告變數時,都是使用相應型別的零值來初始化變數的,陣列也一樣。陣列初始化時,其每個元素都被初始化對應型別的零值。比如下面的整形陣列裡,每個元素都被初始化為0(整形的零值)
var testArr [3]int // 陣列會初始化為零值 [0 0 0]
var testArr = [3]int{1, 2} // 陣列會將未指定的下標值初始化為0值 [1 2 0]
var testArr = [3]int{1, 2, 3} // 陣列使用指定的資料初始化 [1 2 3]
方式2
以上的方式需要保證初始化的陣列長度和指定陣列長度一樣,除此以外我們還可以讓編譯器自己判斷陣列的長度
var testArr = [...]int{1, 2, 3} // 陣列自動指定長度為3 [1 2 3]
方式3
此外還可以透過指定索引值的方式來初始化陣列:
var testArr = [...]int{1:20, 5: 30} // [0 20 0 0 0 30]
陣列的操作
陣列訪問
對於陣列arr[],第一個元素是arr[0],第三個元素是arr[2],總體來說下標i代表的元素是arr[i],最後一個元素是arr[len(arr)-1],超出範圍會報panic。
陣列修改
GO語言透過陣列下標(索引位置)來讀取和修改陣列元素,下標(索引)從0開始,逐漸類推。
陣列是效率很高的資料結構,因為陣列在記憶體分配中是連續的,要訪問陣列裡某個單獨的值,使用[]運算子既可。
陣列的值也可以是指標,下面宣告一個所有元素都是指標的陣列,然後使用*運算子就可以訪問元素指標所指向的值:
// 宣告包含5個元素的指向整數的陣列
// 用整形指標初始化索引為0和1的陣列元素
array := [5]*int{0: new(int), 1: new(int)}
// 為索引0和1的元素賦值
*array[0] = 10
*array[1] = 20
fmt.Println(*array[0])
//輸出為:10
fmt.Println(*array[2])
// 報錯 panic: runtime error: invalid memory address or nil pointer dereference,因為此時 array[2] 沒有指定型別
陣列賦值
在GO語言中,陣列是一個型別值,這意味著陣列也可以像函式一樣用在賦值操作中,變數名代表整個陣列,因此同樣型別的陣列可以賦值類另一個陣列,如:
// 宣告一個包含5個元素的字串陣列
var array1 [5]string
// 宣告第二個包含5個元素的字串陣列並初始化
array2 := [5]string{"a", "b", "c", "d", "e"}
array1 = array2
陣列作為一個變數型別,它包括陣列長度和每個元素的型別兩個部分。只有兩部分都相同的陣列才是型別相同的陣列,才能相互賦值。
陣列的型別
陣列是值型別,賦值和傳參會複製整個陣列。因此改變副本的值,不會改變本身的值。
var array1 [3]string
array2 := [3]string{"", "", ""}
array2[0] = "a"
array2[1] = "b"
array2[2] = "c"
array1 = array2
array2[0] = "d"
fmt.Println(array1[0])
// 輸出a
而在下面操作中,複製操作後,兩個陣列指向同一組字串,修改其中一個陣列的某個值後,另一個陣列的值也相應改變。
// 宣告一個包含3個元素的指向字串的指標陣列
var array1 [3]*string
// 宣告第二個包含3個元素的指向字串的指標陣列,並使用字串指標初始化這個陣列
array2 := [3]*string{new(string), new(string), new(string)}
*array2[0] = "a"
*array2[1] = "b"
*array2[2] = "c"
array1 = array2
*array2[1] = "d"
fmt.Println(*array1[1])
// 輸出d
注意:
- 陣列支援 “==“、”!=” 運算子,因為記憶體總是被初始化過的。
- [n]*T表示指標陣列,*[n]T表示陣列指標.
多維陣列
陣列本身只有一個維度,但是可以組合多個陣列建立多維陣列。多維陣列用於管理具有依賴關係的資料(比如座標系),下面是宣告二維陣列的示例程式碼:
//宣告一個二維整形陣列,兩個維度分別儲存4個元素和2個元素
var array [4][2]int
//使用陣列字面量來宣告並初始化一個二維整形陣列
array := [4][2]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}}
//宣告並初始化外層陣列中索引為1和3的元素
array := [4][2]int{1: {3, 4}, 3: {7, 8}}
//宣告並初始化外層陣列和內層陣列的單個元素
array := [4][2]int{1: {0: 1}, 3: {1: 2}}
訪問單個元素,需要組合[]運算子。如:
array[0][1] = 1
和一維陣列一樣,只要型別一致,就可以將多維陣列互相賦值,又因為每個陣列都是一個單獨的值,所以還可以獨立賦值某個維度,如:
// 將array1的索引為1的維度賦值到一個同型別的新陣列裡
var array3 [2]int = array1[1]
// 將外層陣列的索引為1、內層陣列的索引為0的整形值複製到新的整形變數裡
var value int = array1[1][0]
多維陣列也可以使用...
來編譯器自動判斷陣列長度。但只支援第一層陣列這樣使用。如:
//支援的寫法
a := [...][2]string{
{"北京", "上海"},
{"廣州", "深圳"},
{"成都", "重慶"},
}
//不支援多維陣列的內層使用...
b := [3][...]string{
{"北京", "上海"},
{"廣州", "深圳"},
{"成都", "重慶"},
}
陣列的遍歷
一維陣列遍歷
func main() {
var a = [...]string{"a", "b", "c"}
// 方法1:for迴圈遍歷
for i := 0; i < len(a); i++ {
fmt.Println(a[i])
}
// 方法2:for range遍歷
for index, value := range a {
fmt.Println(index, value)
}
}
二維陣列遍歷
func main() {
a := [3][2]string{
{"北京", "上海"},
{"廣州", "深圳"},
{"成都", "重慶"},
}
for _, v1 := range a {
for _, v2 := range v1 {
fmt.Printf("%s\t", v2)
}
fmt.Println()
}
}
慢慢會把其它資料型別的也做一個整理,做一個合集,希望整理完對自己學習Go會有幫助。
本作品採用《CC 協議》,轉載必須註明作者和本文連結