重學Go語言之數組的具體使用詳解
什麼是數組
什麼是數組?數組是有固定長度的相同數據類型元素的集合, 如下圖所示:
從數組的定義以及上面的示例圖我們可以得到數組的三個特征:
- 固定長度,數組的長度在編譯時就要確定。
- 每個元素的數據類型相同。
- 數組索引從0開始,索引的最大值為數組長度減1。
數組的創建
直接聲明數組變量,在聲明時必須指定長度:
var iArray [2]int var sArray [3]string
上面的代碼中,我們創建瞭一個長度為2
,元素數據類型為int
的數組和一個長度為3
,元素數據類型為string
的數組。
聲明後,就可以通過索引給對應的元素賦值:
iArray[0] = 1 iArray[1] = 2 sArray[0] = "hello" sArray[1] = "world" sArray[2] = "!" fmt.Println(iArray) //輸出 [1,2] fmt.Println(sArray) //輸出 ["hello","world","!"]
也可以在聲明時通過花括號{}
直接初始化數組元素的值:
var iArray [2]int = [2]int{1,2} //花括號內初始化元素數量可以少於數組的長度,後面沒有初始化的元素會被賦予該數據類型的默認值 var sArray [4]string = [4]string{"A","B","C"}
如果在聲明時或者之後沒有通過索引給數組的元素賦值,那麼元素的值為對應數據類型的初始值:
var iArray [3]int var sArray [4]string fmt.Println(iArray) //輸出:[0,0,0] fmt.Println(sArray) //輸出:[]
通知短變量可以讓數組聲明的更簡潔:
i := [2]int{1,2}
也可以在聲明數組不指定數組長度,而是通過...
和花括號{}
內的初始化值讓Go
語言自動推斷數組的長度:
var i = [...]int{1, 2, 3, 4} //數組長度為4
訪問數組的元素
通過索引可以訪問數組中的某個元素:
fmt.Println(iArray[0])
無論是給數組的元素賦值,還是訪問數組的元素都不超過數組的長度,否則會數組越界的錯誤,數組的索引從0開始,因此數組的索引取值范圍是0~len-1
(len表示數組的長度)。
iArray := [2]int{1,2} sArray := [3]string{"A","B","C"} iArray[2] = 10 //報錯,該數組索引的取值范圍是0~1 fmt.Println(sArray[10]) // 報錯,該數組索引的取值范圍是0~2
數組的長度
Go
內置的函數len()
可以用於獲得數組的長度:
iArray := [4]int{1,2,3,4} fmt.Println(len(iArray)) // 輸出結果:4
如何遍歷數組
遍歷數組使用for
語句,有兩種方式:
使用for
語句遍歷數組:
for i := 0; i < len(iArray); i++ { fmt.Println(iArray[i]) }
使用for-range
遍歷數組:
for k,v := range iArray { fmt.Println(k,v) }
for-range
遍歷數組時,可以獲取數組的索引和數組的元素,也可以在遍歷時選擇忽略索引或者元素值:
for _,v := range iArray { //忽略數組的索引 fmt.Println(v) } for k,_ := range iArray{ //忽略元素 fmt.Println(k) }
數組的比較
數組隻能進行相等(==
)或者不相等(!=
)的比較,並且兩個進行比較的數組要符合以下要求,否則代碼無法通過編譯:
- 數組元素的數據類型必須一致
- 數組的長度必須一致
當數組滿足上面的要求後,如果對應索引元素值相同,則數組相等,否則不相等:
iArray1 := [2]int{1, 2} iArray2 := [2]int{1, 2} if iArray1 == iArray2 { print("相等") } else { print("不相等") } //輸出:相等 iArray3 := [2]int{2, 1} iArray4 := [2]int{1, 2} if iArray1 == iArray2 { print("相等") } else { print("不相等") } //輸出:不相等
查找數組中的元素
對於數組來說,要查找數組中是否存在某個元素,並返回其對應索引,就要遍歷一個數組,並對每個元素進行比較:
sArray := [5]string{"Java","PHP","Go","Python","JavaScript"} for index, element := range sArray { if element == needle { fmt.Println(index) } }
如果我們要查找的元素在數組的最後一個,那麼要遍歷整個數組才能查找到,查找元素的時間復雜度為O(n)
。
將數組作為函數參數
把數組作為參數傳遞給函數時,有幾個註意的地方:
- 當把數組作為參數傳給函數時,Go會把數組復制一份傳給函數,所以數組作為函數參數時是值傳遞而不是引用傳遞。
- 數組作為參數,會被復制,因此如果傳遞的數組很大,復制就會很耗時。
- 傳遞給函數的數組,其長度與數據類型必須函數形參一致,因此復用性很差。
func updateArray(haystack [5]int, index int, value int) error { if index >= len(haystack) { return errors.New("索引不能超過數組長度") } haystack[index] = value fmt.Println(haystack) //[1 100 3 4 5] return nil } func main() { iArray := [5]int{1, 2, 3, 4, 5} updateArray(iArray, 1, 100) fmt.Println(iArray) // [1 2 3 4 5] }
上面這個例子中,我們希望updateArray
函數可以修改我們指定索引的元素數組,但實際修改的復制後數組,與我們傳給函數的數組無關,解決的辦法是傳遞數組的指針:
func updateArray(haystack *[5]int, index int, value int) error { if index >= len(haystack) { return errors.New("索引不能超過數組長度") } haystack[index] = value fmt.Println(haystack) //[1 100 3 4 5] return nil } func main() { iArray := [5]int{1, 2, 3, 4, 5} updateArray(&iArray, 1, 100) fmt.Println(iArray) // [1 100 3 4 5] }
雖然傳遞數組指針可以避免數組復制導致的性能問題,但是數組的長度和元素數據類型仍然要求一致,這大概就是數組不怎麼被使用的原因吧:
func main() { iArray := [6]int{1, 2, 3, 4, 5} //把數組長度改為6 updateArray(&iArray, 1, 100) //報錯 }
同理,當我們把一個數組變量賦值另外一個變量時,Go也是把數組復制一份給新的變量,如果想把新的變量指向原來的數組,同樣是用數組的指針:
iArray := [2]int{1,2} iArray1 := iArray iArray[0] = 10 fmt.Println(iArray1) //輸出:[10,2] fmt.Println(iArray) //輸出:[1,2] iArray2 := &iArray iArray2[0] = 20; fmt.Println(iArray2) //輸出:&[20,2] fmt.Println(iArray) //輸出:[20,2]
二維與多維數組
Go也支持二維和多維數組,其創建方式與一維數組類似:
二維數組:
iArrays := [3][2]string{{"A","B"},{"C","D"},{"E","F"}}
上述二維數組的結構如下圖所示:
多維數組:
iArrays := [3][4][2]int{ { {1, 2}, {3, 4}, {5, 6}, }, { {7, 8}, {9, 10}, {11, 12}, }, { {13, 14}, {15, 16}, {17, 18}, }, }
上述三維數組的結構如下圖所示:
小結
總結一下,這篇文章主要講瞭以下幾點:
- 數組是一種固定長度的相同數據類型元素的集合,在實際開發中並不常用,而是作為slice的底層數據結構。
- Go支持一維、二維和多維數組
- 數組可以進行相等或者不相等的比較
- 使用
for
或者for-range
可以遍歷數組 - 通過數組索引訪問元素或者給元素賦值時,都不能超過數組的長度限制。
到此這篇關於重學Go語言之數組的具體使用詳解的文章就介紹到這瞭,更多相關Go語言 數組內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++實現LeetCode(28.實現strStr()函數)
- go實現for range迭代時修改值的操作
- Go 容器遍歷的實現示例
- Go 修改map slice array元素值操作
- mysql中的find_in_set字符串查找函數解析