Go语言里的map底层是通过hash实现的,是一种无序的基于<key, value>对组成的数据结构,key是唯一的,类似python的dict。
map必须初始化后才能写map。
如果只是声明map,但没有初始化,只能读,不能写。参考下面的例子的说明:
package main
import "fmt"
func main() {
var counter map[string]int
/*
map没有初始化,读map相当于读了一个空map
下例中:value是int的零值0,ok是false
*/
value, ok := counter["a"]
fmt.Println(value, ok)
/*counter没有初始化,给counter赋值会在运行时报错
panic: assignment to entry in nil map
*/
counter["a"] = 1
fmt.Println(counter)
}
-
语法
var map_var map[key_data_type]value_data_type = map[key_data_type]value_data_type{} var map_var = map[key_data_type]value_data_type{} map_var := map[key_data_type]value_data_type{} /*cap是map容量,超过后会自动扩容*/ map_var := make(map[key_data_type]value_data_type, [cap])
-
示例
package main import "fmt" func main() { var dict map[string]int = map[string]int{} dict["a"] = 1 fmt.Println(dict) var dict2 = map[string]int{} dict2["b"] = 2 fmt.Println(dict2) dict3 := map[string]int{"test":0} dict3["c"] = 3 fmt.Println(dict2) dict4 := make(map[string]int) dict4["d"] = 4 fmt.Println(dict4) }
-
判断key在map里是否存在
-
语法。
value, is_exist := map[key]
如果key存在,那is_exist就是true, value是对应的值。否则is_exist就是false, value是map的value数据类型的零值。
注意: 如果key不存在,通过map[key]访问不会给map自动插入这个新key。C++是会自动插入新key的,两个语言不一样。如果确定key存在,可以直接使用map[key]拿到value。
-
示例
package main import "fmt" func main() { // 构造一个map str := "aba" dict := map[rune]int{} for _, value := range str{ dict[value]++ } fmt.Println(dict) // map[97:2 98:1] // 访问map里不存在的key,并不会像C++一样自动往map里插入这个新key value, ok := dict['z'] fmt.Println(value, ok) // 0 false fmt.Println(dict) // map[97:2 98:1] // 访问map里已有的key value2 := dict['a'] fmt.Println(value2) // 2 }
-
-
遍历map:使用range迭代,参见lesson14
-
len(map):通过内置的len()函数可以获取map里<key, value>对的数量
counter := make(map[string]int) fmt.Println(len(counter)) counter["a"] = 1 fmt.Println(len(counter))
-
map作为函数形参,可以在函数体内部改变外部实参的值,原理参见Go有引用传递么?。示例如下:
package main import "fmt" func buildMap(str string, m map[rune]int) { /*函数内对map变量m的修改会影响main里的实参mapping*/ for _, value := range str { m[value]++ } } func main() { mapping := map[rune]int{} str := "abc" buildMap(str, mapping) /* mapping的值被buildMap修改了 */ for key, value := range mapping { fmt.Printf("key:%v, value:%d\n", key, value) } }
-
删除key,参数为map和对应的key。允许删除一个不存在的key,对map无任何影响。
package main import "fmt" func main() { dict := map[string]int{"a":1, "b":2} fmt.Println(dict) // map[a:1 b:2] // 删除"a"这个key delete(dict, "a") fmt.Println(dict) // map[b:2] // 删除"c"这个不在的key,对map结果无影响 delete(dict, "c") fmt.Println(dict) // map[b:2] }
-
key必须支持==和!=比较,才能用作map的key。
因此切片slice,函数类型function,集合map,不能用作map的key
-
map不是并发安全的,并发读写要加锁