Golang基礎(chǔ)筆記四之map
本文首發(fā)于公眾號:Hunter后端
原文鏈接:Golang基礎(chǔ)筆記四之map
這一篇筆記介紹 Golang 里 map 相關(guān)的內(nèi)容,以下是本篇筆記目錄:
- map 的概念及其聲明與初始化
- map 的增刪改查
- map 的遍歷
1、map 的概念及其聲明與初始化
map,即映射,是 Golang 里無序鍵值對的集合。
以下是創(chuàng)建 map 的兩種方式。
1. 使用 make 的方式創(chuàng)建
m := make(map[string]int)
m["Hunter"] = 1
fmt.Println(m)
使用 make 進(jìn)行初始化的時候,也可以指定其容量大小:
m := make(map[string]int, 4)
2. 映射字面量初始化
m := map[string]int{
"Hunter": 1,
}
fmt.Println(m)
注意:當(dāng)我們聲明一個 map 之后,它的值是 nil,即 Go 里的空值,一定要對其初始化之后才可向其中添加元素。
比如下面的操作會引發(fā)錯誤:
var m map[string]int
m["Hunter"] = 1 // 錯誤,需要初始化
下面的操作才是正確的操作:
var m map[string]int
m = make(map[string]int)
m["Hunter"] = 1
fmt.Println(m)
介紹這個操作是因?yàn)樵诙嘀?map 或者說嵌套的 map 里很容易忘記這個操作。
3. 多重 map
比如我們想創(chuàng)建一個多重 map,其示例數(shù)據(jù)如下:
{
"張三": {
"number": "00001",
"email": "123@qq.com"
},
"李四": {
"number": "00002",
"email": "456@qq.com"
}
}
我們可以如此操作:
var m = make(map[string]map[string]string)
m["張三"] = make(map[string]string)
m["張三"]["number"] = "00001"
m["張三"]["email"] = "123@qq.com"
m["李四"] = make(map[string]string)
m["李四"]["number"] = "00002"
m["李四"]["email"] = "456@qq.com"
fmt.Println(m)
2、map 的增刪改查
我們先定義一個 map 如下:
m := make(map[string]int)
1. 增
如果想要往其中增加一個 key-value,可以直接添加:
m["a"] = 1
2. 改
如果想要修改其中的值,跟增加一個元素的操作一樣:
m["a"] = 2
3. 查
如果想查詢某個 key 對應(yīng)的 value,可以如下操作:
value := m["a"]
fmt.Println(value)
而如果這個 key 是不存在的,這個操作也不會報(bào)錯,而是會返回對應(yīng) value 類型的零值。
所謂零值,就是變量被聲明但卻未顯式初始化時,系統(tǒng)自動賦予該變量的默認(rèn)值,比如整型變量的零值是 0,布爾型的零值是 false,字符串的零值是空字符串 "" 等。
比如這里我們獲取 key = "b",其返回的結(jié)果就是 int 型的零值 0:
value := m["b"]
fmt.Println(value) // 0
這里如果我們要區(qū)分 map 中這個 key 對應(yīng)的 value 值是 0,還是這個 key 不存在于 map 中的話,有時候會不太好判斷,那么我們可以用另一種方式來操作:
value, exists := m["b"]
if exists {
fmt.Printf("m 存在 key 為 b 的數(shù)據(jù),value 為 %d", value)
} else {
fmt.Printf("m 不存在 key 為 b 的數(shù)據(jù)")
}
4. 刪
如果想要刪除 map 中的某個 key,可以如下操作:
delete(m, "a")
這里,即便是對應(yīng)的 key 不存在于 map 中,這個操作也不會報(bào)錯。
5. 清空 map
如果想要清空一個 map,可以使用 for 循環(huán)對 map 的 key 挨個刪除:
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
fmt.Println(m)
for key, _ := range m {
delete(m, key)
}
fmt.Println(m)
另一種更高效的方案就是重新對其初始化操作:
fmt.Println(m)
m = make(map[string]int)
fmt.Println(m)
3、map 的遍歷
我們可以使用 for 循環(huán)對 map 進(jìn)行遍歷操作:
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
for key, value := range m {
fmt.Printf("Key: %s, Value: %d\n", key, value)
}
1. 按照 key 正序排列遍歷打印
下面這個操作是先將 map 中的 key 做成一個切片,然后對切片進(jìn)行排序,最后再遍歷切片即可。
注意:這里需要引入 sort 模塊
m := map[string]int{
"a": 1,
"b": 3,
"c": 2,
}
keyList := make([]string, 0, len(m))
for key, _ := range m {
keyList = append(keyList, key)
}
sort.Strings(keyList)
for _, key := range keyList {
fmt.Println(key, m[key])
}
2. 按照 key 倒序排列遍歷打印
同樣,這里也是將 key 全部取出來,然后倒序操作:
m := map[string]int{
"a": 1,
"b": 3,
"c": 2,
}
keyList := make([]string, 0, len(m))
for key, _ := range m {
keyList = append(keyList, key)
}
sort.Slice(keyList, func(i, j int) bool {
return keyList[i] > keyList[j]
})
for _, key := range keyList {
fmt.Println(key, m[key])
}
3. 按照 value 正序排列遍歷打印
對 value 進(jìn)行排序,這里的做法是先定義一個結(jié)構(gòu)體 struct,然后將 map 中的 key-value 賦值到這個 struct,做成一個 struct 切片,然后對結(jié)構(gòu)體切片按 value 進(jìn)行排序。
這里結(jié)構(gòu)體的概念會在后面介紹,這里先直接使用:
m := map[string]int{
"a": 1,
"b": 3,
"c": 2,
}
type kv struct {
Key string
Value int
}
var sortedKV []kv
for k, v := range m {
sortedKV = append(sortedKV, kv{k, v})
}
sort.Slice(sortedKV, func(i, j int) bool {
return sortedKV[i].Value < sortedKV[j].Value
})
for _, kv := range sortedKV {
fmt.Printf("%s: %d\n", kv.Key, kv.Value)
}
4. 按照 value 倒序排列遍歷打印
按照 value 倒序排列的方式與按 value 正序排列的方式類似,只是需要將排序規(guī)則改為 > 即可:
m := map[string]int{
"a": 1,
"b": 3,
"c": 2,
}
type kv struct {
Key string
Value int
}
var sortedKV []kv
for k, v := range m {
sortedKV = append(sortedKV, kv{k, v})
}
sort.Slice(sortedKV, func(i, j int) bool {
return sortedKV[i].Value > sortedKV[j].Value
})
for _, kv := range sortedKV {
fmt.Printf("%s: %d\n", kv.Key, kv.Value)
}

浙公網(wǎng)安備 33010602011771號