資料結構
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) // 5Slices
動態長度的資料序列,是 Array 的抽象。
Array vs Slice
| 特性 | Array | Slice |
|---|---|---|
| 長度 | 固定 | 動態 |
| 宣告 | [5]int | []int |
| 傳遞 | 複製整個陣列 | 傳遞參照 |
| 比較 | 可用 == | 不可直接比較 |
Slice 內部結構
Slice 包含三個元素:
type slice struct {
ptr *array // 指向底層 array 的指標
len int // 長度
cap int // 容量
}
建立 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=10Slice 操作
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) // 緩衝大小 10Strings and Runes
- Go string 是唯讀的 byte slice
rune:type byte = uint8type rune = int32(int32的別名)
- 代表一個 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)