iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
Modern Web

就是個Go,我也可以啦!GOGO系列 第 9

2023鐵人賽 Day 9 Go的資料結構-陣列

  • 分享至 

  • xImage
  •  

再經過了這麼多章節的探討go的基本原理後,我們今天要來面對的是go的資料結構,由於go的資料結構特別,所以我想要留到後面再來講,像是,我們熟悉的陣列,在go裡面其實有分成陣列和切片,他們的使用也有非常不一樣的地方

陣列

陣列是一組在記憶體中連續位置的資料結構,因為是連續位置,所以我們能透過所引來訪問

在初始化時,有兩種方式,取決於你知不知道這個陣列的大小

arr1 := [3]int{1, 2, 3}
arr2 := [...]int{1, 2, 3}

第一種是固定陣列長度,第二種是不固定

再來,我們先來看source code

func NewArray(elem *Type, bound int64) *Type {
	if bound < 0 {
		Fatalf("NewArray: invalid bound %v", bound)
	}
	t := New(TARRAY)
	t.Extra = &Array{Elem: elem, Bound: bound}
	t.SetNotInHeap(elem.NotInHeap())
	return t
}

從這段source code我們可以得到幾種認知

  • 陣列是固定大小的: bound 參數指定了陣列的大小。當你在 Go 中創建一個陣列,你需要指定它的大小,且一旦指定,其大小就不能更改
    • 但,不是可以不指定大小嗎 arr2 := [...]int{1, 2, 3}
    • 事實上是,go在編譯時會去判斷這個陣列的大小 {1, 2, 3} 為3,並指定
  • 陣列具有特定的元素類型: elem 參數指定了陣列元素的類型。這確保了陣列中所有的元素都是同一類型
  • 類型和邊界檢查: 代碼中首先檢查 bound 是否小於 0。這是一種確保不創建具有無效大小的陣列的方法。此檢查避免了潛在的錯誤或不正確的使用情況
  • 具體的陣列結構: 代碼創建了一個新的 TARRAY 類型的物件,然後為它設置了與陣列相關的額外資料,這包括元素的類型 (Elem) 和陣列的大小 (Bound)

陣列的迭代

Go 的 for 迴圈可以使用迭代器 (iterator)

package main

import (
	"fmt"
)

func main() {
	var arr [4]string

	arr = [4]string{"q", "d", "aa", "cc"}
	fmt.Println(arr)

	for i, e := range arr {
		fmt.Println(fmt.Sprintf("%d: %s", i+1, e))
	}
}

如果要改變陣列裡面的元素的話可以這樣做

package main

import (
	"fmt"
)

func main() {
	var arr [4]string

	arr = [4]string{"q", "d", "aa", "cc"}
	fmt.Println(arr)

	for i := 0; i < len(arr); i++ {
		arr[i] = arr[i] + "aa"
	}
	fmt.Println(arr)
}

限制

從上面可以發現go的陣列是把類型和大小綁在一起的,當你宣告完後go會開出你指定大小的連續記憶體空間,故如果你把長度為8的陣列塞到長度為5的陣列,那就會報錯

func printArray(a [5]int) {
	fmt.Println(a)
}

func main() {
	var example = [8]int{1, 2, 3, 4, 5, 6, 7, 8}
	printArray(example)
}

此時編譯完後會顯示

var example [8]int

cannot use example (variable of type [8]int) as [5]int value in argument to printArraycompilerIncompatibleAssign

固定大小的陣列(array)一旦被定義,其大小就不能更改。這意味著你不能像在某些其他程式語言中那樣使用 pushpop 操作來動態地添加或移除元素

特殊創建array及方法

  • 在 go 中,我們也可以在宣告時初始化陣列的特定元素
package main
import "fmt"

func main() {

  initOnlySpecficIndex := [4]int{0: 3, 2: 4}

  fmt.Println(initOnlySpecficIndex)
   // [3,0,4,0]
}
  • 計算陣列長度

    • 可以使用len(
    package main
    
    import "fmt"
    
    func main() {
        arr := [5]int{1, 2, 3, 4, 5}
        length := len(arr)
        fmt.Println("Length of the array:", length)
    }
    
    

    Output:

    Length of the array: 5
    
    
  • 多為陣列

    • 我們經常使用的都是一維陣列,但在golang,可以使用多為陣列
    • 我們可以想成一個簡易的資料表,
    • 假設我們需要紀錄學生的成績,每一列為科目,每一行為學生成績
    scores := [3][3]int{
        {90, 85, 78},  // 學生 1 的分數
        {76, 85, 88},  // 學生 2 的分數
        {78, 90, 79},  // 學生 3 的分數
    }
    

上一篇
2023鐵人賽Day 8 理解Go設計哲學-2
下一篇
2023鐵人賽Day 10 Go的資料結構-slice
系列文
就是個Go,我也可以啦!GOGO30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言