Calvert's murmur

在 Golang 中使用陣列

2019-11-12

約 5009 字 / 需 27 分鐘閱讀

原文:CalliCoderWorking with Arrays in Golang

陣列是固定長度的相同型別元素的集合。陣列的元素按順序儲存,並且可以使用它們的 index 來存取。

在 Golang 中宣告陣列

你可以像這樣宣告一個長度為 n 且型別為 T 的陣列:

var a[n]T

舉例來說,以下是如何宣告一個長度為 10 的整數陣列:

// An array of 10 integers
var a[10]int

現在,讓我們看一個完整範例:

package main

import "fmt"

func main() {
	var x [5]int // An array of 5 integers
	fmt.Println(x)

	var y [8]string // An array of 8 strings
	fmt.Println(y)

	var z [3]complex128 // An array of 3 complex numbers
	fmt.Println(z)
}
# Output
[0 0 0 0 0]
[       ]
[(0+0i) (0+0i) (0+0i)]

預設情況下,所有陣列元素皆使用與陣列型別一致的零值初始化。

舉例來說,如果我們宣告一個整數陣列,則所有元素都將以 0 初始化。如果我們宣告一個字串陣列,則所有元素都將以空字串 "" 初始化,依此類推。

透過索引存取陣列元素

陣列的元素按順序儲存,可以透過它們的 index 存取。index 從零開始,結束於 length - 1

package main

import "fmt"

func main() {
	var x [5]int // An array of 5 integers

	x[0] = 100
	x[1] = 101
	x[3] = 103
	x[4] = 105

	fmt.Printf("x[0] = %d, x[1] = %d, x[2] = %d\n", x[0], x[1], x[2])
	fmt.Println("x = ", x)
}
# Output
x[0] = 100, x[1] = 101, x[2] = 0
x =  [100 101 0 103 105]

在上面的範例中,由於我們沒有分派 x[2] 任何值,因此它的值為 0(整數的零值)。

使用陣列定數初始化陣列

你可以像這樣同時宣告並初始化陣列:

// Declaring and initializing an array at the same time
var a = [5]int{2, 4, 6, 8, 10}

上面表達式右側的陳述式稱為陣列定數。

注意,我們不需要像 var a [5]int 中那樣指定變數 a 的型別,因為編譯器可以從右側的表達式自動推斷型別。

你也可以使用 Golang 的簡短變數宣告來宣告和初始化陣列。上面的陣列宣告也可以在任何函數內撰寫如下:

// Short hand declaration
a := [5]int{2, 4, 6, 8, 10}

這是一個完整範例:

package main

import "fmt"

func main() {
	// Declaring and initializing an array at the same time
	var a = [5]int{2, 4, 6, 8, 10}
	fmt.Println(a)

	// Short declaration for declaring and initializing an array
	b := [5]int{2, 4, 6, 8, 10}
	fmt.Println(b)

	// You don't need to initialize all the elements of the array.
	// The un-initialized elements will be assigned the zero value of the corresponding array type
	c := [5]int{2}
	fmt.Println(c)
}
# Output
[2 4 6 8 10]
[2 4 6 8 10]
[2 0 0 0 0]

讓 Go 編譯器推斷陣列的長度

你還可以從陣列的初始化表達式中省略長度宣告,並讓編譯器為你計算元素的數量:

package main

import "fmt"

func main() {
	// Letting Go compiler infer the length of the array
	a := [...]int{3, 5, 7, 9, 11, 13, 17}
	fmt.Println(a)
}
# Output
[3 5 7 9 11 13 17]

探索有關 Golang 陣列的更多資訊

  1. 陣列的長度是其型別的一部分

陣列的長度是其型別的一部分。因此陣列 a[5]inta[10]int 是完全不同的型別,且你不能將一個分派給另一個。

也就是說你無法調整陣列長度,因為調整陣列的長度將意味著更改其型別,而你無法在 Golang 中更改變數的型別。

package main

func main() {
	var a = [5]int{3, 5, 7, 9, 11}
	var b [10]int = a  // Error, a and b are distinct types
}
  1. Golang 中的陣列是數值型別

Golang 中的陣列是數值型別,不像其他語言,如 C、C++ 和 Java 的陣列是參考型別。

這意味著當你將陣列賦值給新變數或將陣列傳遞給函數時,將複製整個陣列。因此,如果你對此複製的陣列進行任何更改,原始陣列將不會受到影響且保持不變。

這有一個範例:

package main

import "fmt"

func main() {
	a1 := [5]string{"English", "Japanese", "Spanish", "French", "Hindi"}
	a2 := a1 // A copy of the array `a1` is assigned to `a2`

	a2[1] = "German"

	fmt.Println("a1 = ", a1) // The array `a1` remains unchanged
	fmt.Println("a2 = ", a2)
}
# Output
a1 =  [English Japanese Spanish French Hindi]
a2 =  [English German Spanish French Hindi]

在 Golang 中迭代陣列

你可以像這樣使用 for 迴圈迭代陣列:

package main

import "fmt"

func main() {
	names := [3]string{"Mark Zuckerberg", "Bill Gates", "Larry Page"}

	for i := 0; i < len(names); i++ {
		fmt.Println(names[i])
	}
}
# Output
Mark Zuckerberg
Bill Gates
Larry Page

上面的範例中,len() 函數用於找出陣列的長度。

讓我們來看另一個範例。在下面的範例中,我們透過迭代陣列,將元素逐一加到變數 sum 中,找出陣列所有元素的總和:

package main

import "fmt"

func main() {
	a := [4]float64{3.5, 7.2, 4.8, 9.5}
	sum := float64(0)

	for i := 0; i < len(a); i++ {
		sum = sum + a[i]
	}

	fmt.Printf("Sum of all the elements in array  %v = %f\n", a, sum)
}
# Output
Sum of all the elements in array  [3.5 7.2 4.8 9.5] = 25.000000

使用 range 迭代陣列

Golang 使用 range 運算子提供了一種更強大的 for 迴圈形式。以下是如何將 range 運算子與 for 迴圈一起使用來迭代陣列:

package main

import "fmt"

func main() {
	daysOfWeek := [7]string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}

	for index, value := range daysOfWeek {
		fmt.Printf("Day %d of week = %s\n", index, value)
	}
}
# Output
Day 0 of week = Mon
Day 1 of week = Tue
Day 2 of week = Wed
Day 3 of week = Thu
Day 4 of week = Fri
Day 5 of week = Sat
Day 6 of week = Sun

現在,讓我們使用 range 形式的 for 迴圈來撰寫一個與普通 for 迴圈相同的 sum 範例:

package main

import "fmt"

func main() {
	a := [4]float64{3.5, 7.2, 4.8, 9.5}
	sum := float64(0)

	for index, value := range a {
		sum = sum + value
	}

	fmt.Printf("Sum of all the elements in array %v = %f", a, sum)
}

當你執行上面的程式時,它會產生以下錯誤:

# Output
./array_iteration_range.go:9:13: index declared and not used

Go 編譯器不允許建立從未使用過的變數。你可以透過使用 _(底線) 代替 index 來解決此問題:

package main

import "fmt"

func main() {
	a := [4]float64{3.5, 7.2, 4.8, 9.5}
	sum := float64(0)

	for _, value := range a {
		sum = sum + value
	}

	fmt.Printf("Sum of all the elements in array %v = %f", a, sum)
}

底線(_)用於告訴編譯器我們不需要此變數。上面的程式現在可以成功執行並輸出陣列的總和:

# Output
Sum of all the elements in array [3.5 7.2 4.8 9.5] = 25.000000

Golang 中的多維陣列

到目前為止,我們在本文中建立的所有陣列都是一維的。你也可以在 Golang 中建立多維陣列。

以下範例示範了如何建立多維陣列:

package main

import "fmt"

func main() {
	a := [2][2]int{
		{3, 5},
		{7, 9},	// This trailing comma is mandatory
	}
	fmt.Println(a)

	// Just like 1D arrays, you don't need to initialize all the elements in a multi-dimensional array.
	// Un-initialized array elements will be assigned the zero value of the array type.
	b := [3][4]float64{
		{1, 3},
		{4.5, -3, 7.4, 2},
		{6, 2, 11},
	}
	fmt.Println(b)
}
# Output
[[3 5] [7 9]]
[[1 3 0 0] [4.5 -3 7.4 2] [6 2 11 0]]

結論

陣列很有用,但由於其固定長度而造成的限制而有些不靈活。這就是為什麼 Go 提供了另一個名為 Slice 的資料結構,該資料結構建構在陣列之上,並提供了我們所需的所有靈活性。在下一篇文章中,我們將學習 Slice。

Tags: Golang