重學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!

推薦閱讀: