[Golang] maps
在 Go 中,Map 也是 Key-Value pair 的組合,但是 Map 所有 Key 的資料型別都要一樣;所有 Value 的資料型別也要一樣。另外,在設值和取值需要使用 [] 而非 .。map 的 zero value 是 nil。
The anatomy of maps in Go @ run go
建立 Map 的方式
// m := map[Tkey]Tvalue{}
func main() {
	// 第一種方式
	// 建立一個型別為 map 的變數,其中的 key 都會是 string,value 也都會是 string
	colors := map[string]string{}
	// 也可以直接帶值
	colors := map[string]string{
		"red":   "#ff0000",
		"green": "#4bf745",
	}
	// 第二種方式
	var colors map[string]string
	// 第三種方式,使用 make 建立 Map。
	// Key 的型別是 string,Value 是 int
	colors := make(map[string]int)
	colors["red"] = 10
	fmt.Println(colors) // map[red:10]
	// 如果對於鍵值的數量有概念的話,也可以給定初始大小,將有助於效能提升(The little Go book)
	m := make(map[string]int, 100)
}
Map 的 value 是 struct
// Map 的 value 是 struct
type Vertex struct {
	Lat, Long float64
}
func main() {
	// 使用 make 建立 Map
	m := make(map[string]Vertex)
	m["Bell Labs"] = Vertex{
		40.68443, -74.39967,
	}
	// 使用 Map Literal 建立 Map
	mapLiteral := map[string]Vertex{
		"Bell Labs": Vertex{
			40.68433, -74.39967,
		},
		"Google": Vertex{
			37.42202, -122.08408,
		},
	}
	// Struct Type 的名稱可以省略
	mapLiteral := map[string]Vertex{
		"Bell Labs": {
			40.68433, -74.39967,
		},
		"Google": {
			37.42202, -122.08408,
		},
	}
}
Map 的操作
keywords: delete, len
在 map 中因為 key 本身是有資料型別的,因此只能使用 [] 來設值和取值,不能使用 .:
- 使用 len()可以取得 map 鍵值的數量
- 使用 delete(map, key)可以移除 map 中的鍵值
- 使用 value, isExist := m[key]可以用來取值,同時判斷該key是否存在
func main() {
	colors := make(map[int]string)
	// 先增 map 中的 key-value
	colors[10] = "#ffffff"
	colors[1] = "#4bf745"
	// 使用 len 可以取得 map 鍵值的數量
	fmt.Println(len(colors)) // 2
	// 移除 map 中的資料,delete(m, key)
	delete(colors, 10)
	// 取值
	fmt.Println(colors[10])
	// 檢查某 Map 中是否存在該 key
	// value, isExist = m[key]
	//
	// 該 key 存在的話 isExist 會是 true,否則會是 false
	// 該 key 存在的話 value 會回傳該 map 的值,否則回傳該其 zero value
	value, isExist := colors[1] // #4bf745 true
	value, isExist = colors[10] // "", false
}
Map 的疊代
keywords: range
func main() {
	colors := map[string]string{
		"red":   "#ff0000",
		"green": "#4bf745",
		"white": "#ffffff",
	}
	// 疊代 map
	printMap(colors)
}
// 因為 map 是 reference type,所以不用使用 pointer
func printMap(c map[string]string) {
	for color, hex := range c {
		fmt.Printf("%v: %v\n", color, hex)
	}
}
Map 和 Structure 的選擇
| Map | Structure | 
|---|---|
| 所有的 key 都需要是相同型別 | |
| 所有的 value 都需要是相同型別 | value 可以是不同型別 | 
| Key 有被 indexed,因此可以進行疊代,列出所有的 key-value pairs | Key 沒有被 indexed,因此沒辦法透過疊代的方式列出所有的 key-value pair | 
| Reference Type | Value Type | 
| 通常用在資料集合關聯性非常強的資料,例如 colors | 通常用在一個帶有多種屬性的東西,例如 person | 
| 不用一開始就知道所有的 key 有哪些,因為可以後續新增和刪除 | 需要一開始就清楚定義所有的欄位 |