在其他語言諸如C++/Java中, map一般都以庫的方式提供 如C++中的 std::map<> ,Java中的Hashmap<>,在golang中map為內(nèi)置類型,不需要引用任何庫.
map是一堆未排序鍵值對的集合,map的key必須為可比較類型,比如 == 或 !=,map查找比線性查找快,但慢于索引查找(數(shù)組,切片)
定義一個(gè)map
格式 var name map[keytype]valuetype
其中的keytype為map中鍵的類型,valuetype為map中值的類型,map還可以使用 := 或者 make()創(chuàng)建,如:
var a map[int]int
var b = map[string]string{}
c := map[string]bool{}
d := make(map[string]int)
map的初始化
map類似于數(shù)組和切片,可以在定義時(shí)直接指定初始值 如:
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
map元素訪問
上邊定義并初始化了一個(gè)map,那么如何訪問一個(gè)map中的元素呢?
可以通過鍵(key)來訪問指定的value 如:
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
fmt.Println(a["name"],a["age"])
上述程序?qū)⑤敵? zhangsan 16
將上述的代碼修改一下
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
fmt.Println(a["name"], a["age"], a["parent"])
map中并沒有parent這個(gè)鍵,在諸如C++/Java或其他語言中,如果訪問一個(gè)并不存在的鍵,將直接導(dǎo)致程序異常,所以判斷一個(gè)map中是否存在某個(gè)鍵,就成了必需的步驟,但在golang中,這些都不是問題
上述代碼不會(huì)發(fā)生任何異?;蛘弋a(chǎn)生警告
在golang中 如果訪問一個(gè)未定義的key 將返回這個(gè)map中value的默認(rèn)值,來驗(yàn)證一下
package main
import (
"fmt"
)
func main() {
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
fmt.Println(a["parent"])
if a["parent"] == "" {
fmt.Println("yes")
}
var b = map[int]int{1: 1, 2: 2}
fmt.Println(b[3])
if b[3] == 0 {
fmt.Println("yes")
}
}
上述程序?qū)⑤敵?br>
//這個(gè)是空字符串
yes
0
yes
但顯然我們并不想要這個(gè)結(jié)果,golang中提供了一種方式來判斷數(shù)組中是否含有某個(gè)鍵
格式 value,bool := map[key] 如下列程序
func main() {
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
if value, ok := a["parent"]; ok == true {
fmt.Println(value)
} else {
fmt.Println("key not in map")
}
}
注意:golang中過的if語句中定義的變量在語句塊外是訪問不到的
修改map中的元素
和數(shù)組一樣,可以使用key來修改map中的元素
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
fmt.Println(a)
a["name"] = "李四"
fmt.Println(a)
上述代碼將輸出
map[name:zhangsan age:16 sex:男]
map[name:李四 age:16 sex:男]
新增元素
與slice不同,map元素的新增不需要使用copy()函數(shù) 可以直接 map[key] = value 的方式增加元素 如:
package main
import (
"fmt"
)
func main() {
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
a["girlfriend"] = "蒼老師"
fmt.Println(a)
}
刪除元素
比slice相比,map提供delete()函數(shù)進(jìn)行元素的刪除
格式 delete(map,key) 如下例:
package main
import (
"fmt"
)
func main() {
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
delete(a, "name")
fmt.Println(a)
}
以上程序?qū)ap[age:16 sex:男]
map是引用類型
map是引用類型,來看一個(gè)簡單的例子
func main() {
var a = map[int]int{1: 1, 2: 2}
b := a
a[1] = 123456
fmt.Println(a, b)
}
以上程序會(huì)輸出 map[1:123456 2:2] map[1:123456 2:2]
我們再傳遞進(jìn)函數(shù)里面測試下,關(guān)于函數(shù)的定義后面我們會(huì)講,此處只是一個(gè)demo
func main() {
var a = map[int]int{1: 1, 2: 2}
b := a
test(a)
fmt.Println(a, b)
}
func test(a map[int]int) {
a[1] = 111
}
以上程序會(huì)輸出 map[2:2 1:111] map[1:111 2:2] 或者 map[1:111 2:2] map[1:111 2:2]
為什么呢?仔細(xì)思考一下,這是否再一次說明了map是無序的呢?
map的遍歷
與數(shù)組類似 map也可以使用 for range關(guān)鍵字來進(jìn)行遍歷
var a = map[string]string{"name": "zhangsan", "age": "16", "sex": "男"}
for key, value := range a {
fmt.Println(key, value)
}