陣列:Go語言中的數據小倉庫
👨💻簡介
陣列就像是一個儲存相同類型資料的容器,你可以想像成裝滿了一樣東西的盒子,每個東西都叫做陣列元素。這種類型可以是基本的,像是整數或字串,也可以是你自己定義的型別。不過陣列有個限制,就是大小一旦確定就無法改變。在Go語言裡,陣列的長度也是型別的一部分。舉例來說,[5]int和[10]int就是不同的型別。雖然它們都是整數陣列,但因為長度不同,所以視為不同的資料型別,不能直接互相給值或操作。這麼做是為了在長度上更加嚴謹,不會混淆不同大小的陣列,增加了資料的安全性。
另一個類似的東西是切片(Slice),這東西可以想像成動態的序列,可以根據需要自由地增加或減少。不過,為了更好地理解切片,我們先學學陣列的使用。
陣列的基本概念
陣列是由一組元素所組成的固定大小的資料結構,每個元素都有一個相應的索引。陣列的大小在宣告時就需要確定,並且在後續操作中無法改變。
宣告和初始化陣列
在 Go 中,宣告和初始化陣列可以使用以下的語法:
var arr1 [3]int // 創建一個整數陣列,大小為 3
arr2 := [4]string{"A", "B"} // 創建一個包含 4 個字串元素的陣列
arr3 := [...]int{1, 2, 3} // 自動推斷陣列大小為 3
你也可以在宣告陣列的同時,使用指定索引的方式來初始化陣列:
arr := [...]int{1: 10, 3: 30} // 陣列的值為 [0 10 0 30]
陣列的基本操作
取得陣列元素
陣列的元素可以通過索引來存取,索引從 0 開始計數。
numbers := [5]int{10, 20, 30, 40, 50}
firstNumber := numbers[0] // 存取第一個元素,值為 10
secondNumber := numbers[1] // 存取第二個元素,值為 20
假設我們有一個陣列 arr := [5]int{1, 2, 3, 4, 5}
。
arr[:]
表示整個陣列:
arr := [5]int{1, 2, 3, 4, 5}
arr_new := arr[:]
fmt.Println(arr_new) // 輸出:[1 2 3 4 5]
arr[i:]
表示從索引i
到陣列末尾的陣列:
arr := [5]int{1, 2, 3, 4, 5}
startIndex := 2
arr_new := arr[startIndex:]
fmt.Println(arr_new) // 輸出:[3 4 5]
arr[:i]
表示從陣列開頭到索引i-1
的切片:
arr := [5]int{1, 2, 3, 4, 5}
endIndex := 3
arr_new := arr[:endIndex]
fmt.Println(arr_new) // 輸出:[1 2 3]
修改陣列元素
我們可以修改陣列中的元素,例如:
var arr = [...]int{1, 2, 3}
arr[0] = 5
fmt.Println(arr) // 輸出:[5 2 3]
遍歷陣列
可以使用傳統的索引方式或 range
來遍歷陣列中的元素:
numbers := [5]int{10, 20, 30, 40, 50}
// 使用傳統的索引方式遍歷陣列
for i := 0; i < len(numbers); i++ {
fmt.Println(numbers[i])
}
// 使用 range 遍歷陣列
for _, num := range numbers {
fmt.Println(num)
}
for i := range numbers {
fmt.Println(numbers[i])
}
range
是一個內建函式,用於遍歷陣列、切片、映射等集合型資料。在這個範例中,我們使用 range
來遍歷 numbers
陣列中的每個元素,並將每個元素的值賦值給 num
變數。
陣列的特性、限制與使用場景
陣列的特性
- 固定大小: 陣列在宣告時需要確定大小,且大小不可改變。這意味著一旦陣列被創建,其大小將保持不變。
- 相同類型元素: 陣列內的元素必須是相同的類型,可以是內建的基本數據類型(如整數、浮點數)或自定義的結構體。
- 連續儲存: 陣列中的元素在記憶體中是連續儲存的,這有助於提高存取效率,因為 CPU 可以預取接下來的元素。
- 值類型: 陣列是值類型,當陣列被賦值給另一個陣列時,實際上是對數據的複製,而不是引用。
陣列是值類型,這意味著當你賦值或傳遞陣列時,實際上是複製整個陣列的內容。因此,對副本的修改不會影響原始陣列的值:
var array1 = [...]int{1, 2, 3}
array2 := array1
array2[0] = 3
fmt.Println(array1, array2) // 輸出:[1 2 3] [3 2 3]
這上面的代碼展示了陣列的值類型特性。改變array2
的值並不會影響array1
的值。
陣列的限制
- 固定大小: 陣列在宣告時需要指定固定的大小,且無法在運行時動態改變。這意味著陣列的容量是固定的,可能會限制資料集合的彈性。
- 資源浪費: 如果分配了比實際使用更大的陣列,可能會浪費記憶體。而若分配比需求小的陣列,可能會限制數據的存儲。
- 不適合動態資料: 由於固定大小,陣列不太適合儲存動態增減的資料集合,這方面切片(Slice)更適合。
使用場景
- 固定大小需求: 當你確定資料集合的大小是固定的,且不會變動時,陣列是一個不錯的選擇,如一週的天數、一個月的天數等。
- 簡單的資料儲存: 如果你僅需要儲存一些數值,且不需要動態調整大小,陣列可以很好地滿足需求。
- 記憶體效能要求: 陣列在記憶體中是連續儲存的,這可以提供更好的存取效能,特別是當資料量較小時。
- 多維資料: 陣列可以用於建立多維資料結構,例如矩陣,如果資料的結構相對固定,陣列是一個不錯的選擇。
- 資料安全性: 陣列的大小固定,這可以防止意外的資料溢位,有助於維護資料的安全性。
常見用法
- 取得陣列長度
使用內建函式
len()
即可取得陣列長度
var a[10]int
fmt.Println(len(a))
- 計算陣列元素總和
numbers := [5]int{10, 20, 30, 40, 50}
var sum int
for _, num := range numbers {
sum += num
}
fmt.Println("總和:", sum) // 輸出總和:150
- 計算陣列元素平均值
numbers := [5]float64{98, 93, 77, 82, 83}
var sum float64
for _, num := range numbers {
sum += num
}
average := sum / float64(len(numbers))
fmt.Printf("平均值:%.2f\n", average) // 輸出平均值:86.60
- 尋找最大和最小值
numbers := [5]int{10, 20, 30, 40, 50}
max := numbers[0]
min := numbers[0]
for _, num := range numbers {
if num > max {
max = num
}
if num < min {
min = num
}
}
fmt.Println("最大值:", max) // 輸出最大值:50
fmt.Println("最小值:", min) // 輸出最小值:10
- 陣列反轉
numbers := [5]int{10, 20, 30, 40, 50}
reversedNumbers := [5]int{}
for i, j := 0, len(numbers)-1; i < len(numbers); i, j = i+1, j-1 {
reversedNumbers[j] = numbers[i]
}
fmt.Println("反轉陣列:", reversedNumbers) // 輸出反轉陣列:[50 40 30 20 10]
小結
陣列在Go語言中是一個基本的資料結構,用來固定儲存相同類型的元素。雖然使用受限,但在需要保持順序和固定大小的資料集合時非常實用。它在儲存資料、計算總和、平均值等方面扮演重要角色。陣列能透過索引初始化,特定位置賦值,其他位置保留預設值。無論使用索引或range,都能輕鬆迭代陣列元素,進行各種操作。陣列值需相同類型,且在記憶體中連續儲存,存取效率高。但記住,陣列大小固定,儲存可變數量元素可考慮使用切片。