首頁 > 軟體

重學Go語言之陣列的具體使用詳解

2023-02-28 18:00:17

什麼是陣列

什麼是陣列?陣列是有固定長度的相同資料型別元素的集合, 如下圖所示:

從陣列的定義以及上面的範例圖我們可以得到陣列的三個特徵:

  • 固定長度,陣列的長度在編譯時就要確定。
  • 每個元素的資料型別相同。
  • 陣列索引從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語言 陣列內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com