資料結構

Go 語言內建資料結構:Array、Slice、Map、Struct。

Arrays

固定長度的資料序列。

// 宣告
var arr [5]int                      // 零值初始化
arr := [5]int{1, 2, 3, 4, 5}        // 字面值初始化
arr := [...]int{1, 2, 3}            // 自動推斷長度

// 存取
arr[0] = 10
fmt.Println(arr[0])

// 長度
len(arr) // 5

Slices

動態長度的資料序列,是 Array 的抽象。

Array vs Slice

特性ArraySlice
長度固定動態
宣告[5]int[]int
傳遞複製整個陣列傳遞參照
比較可用 ==不可直接比較

Slice 內部結構

Slice 包含三個元素:

type slice struct {
    ptr *array  // 指向底層 array 的指標
    len int     // 長度
    cap int     // 容量
}
Slice Internal Structure

建立 Slice

// 字面值
grades := []int{10, 20, 30}

// 從 array
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // [2, 3, 4]

// make
slice := make([]int, 5)      // len=5, cap=5
slice := make([]int, 5, 10)  // len=5, cap=10

Slice 操作

movies := []string{"Avatar", "Titanic", "Inception", "Interstellar", "The Dark Knight"}

// 複製所有元素(參照相同底層 array)
allmovies := movies[:]

// 取得 index 0 到 2(不含 2)
movies[:2] // ["Avatar", "Titanic"]

// 取得 index 3 到最後
movies[3:] // ["Interstellar", "The Dark Knight"]

// append
movies = append(movies, "Tenet")

// 長度與容量
len(movies) // 6
cap(movies) // 依底層 array 而定

Copy Slice

src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src) // dst 與 src 獨立

Maps

鍵值對資料結構。

// 建立
m := make(map[string]int)
m := map[string]int{"a": 1, "b": 2}

// 新增/修改
m["key"] = 100

// 讀取
value := m["key"]

// 檢查 key 是否存在
if value, ok := m["key"]; ok {
    fmt.Println("Found:", value)
}

// 刪除
delete(m, "key")

// 遍歷
for key, value := range m {
    fmt.Println(key, value)
}
Map 的遍歷順序是隨機的,不保證順序。

Structs

結構化資料類型,用於組織相關欄位。

Go 的 structs 是具型別的欄位集合,適合用於組織資料形成記錄。
type Person struct {
    Name string
    Age  int
}

// 建立
p1 := Person{Name: "Alice", Age: 30}
p2 := Person{"Bob", 25}  // 順序必須與定義相同
p3 := &Person{Name: "Charlie"}

// 存取
p1.Name = "Alice Updated"

Struct Tags

用於元資料,常見於 JSON、資料庫映射。

type User struct {
    ID        int    `json:"id" db:"user_id"`
    Name      string `json:"name" db:"user_name"`
    Email     string `json:"email,omitempty"`
    Password  string `json:"-"` // 忽略此欄位
    CreatedAt time.Time `json:"created_at" db:"created_at"`
}
Tag說明
json:"name"JSON 欄位名稱
json:",omitempty"空值時省略
json:"-"忽略此欄位
db:"column"資料庫欄位映射

Struct Embedding

結構體嵌入可將方法「繼承」給其他結構體。

type Animal struct {
    Name string
}

func (a Animal) Speak() {
    fmt.Println(a.Name, "makes a sound")
}

type Dog struct {
    Animal  // 嵌入
    Breed string
}

func main() {
    d := Dog{Animal: Animal{Name: "Buddy"}, Breed: "Golden"}
    d.Speak()  // 可直接呼叫 Animal 的方法
    d.Name     // 可直接存取 Animal 的欄位
}

make 函式

內建函式,用於建立 slice、map、channel。

// Slice
slice := make([]int, 5)       // len=5, cap=5
slice := make([]int, 5, 10)   // len=5, cap=10

// Map
m := make(map[string]int)
m := make(map[string]int, 100) // 預留 100 個元素空間

// Channel
ch := make(chan int)     // 無緩衝
ch := make(chan int, 10) // 緩衝大小 10

Strings and Runes

  • Go string 是唯讀的 byte slice
  • rune
    • type byte = uint8
    • type rune = int32int32 的別名)
  • 代表一個 Unicode code point
s := "Hello, 世界"

// 長度
len(s)          // byte 數量: 13
len([]rune(s))  // 字元數量: 9

// 遍歷
for i, r := range s {
    fmt.Printf("%d: %c\n", i, r)
}

// 轉換
bytes := []byte(s)
runes := []rune(s)

相關主題