字典是存储键值对的、无序的集合。字典中每一个key
都是唯一的,且支持相等运算符(==,!=
)。,比如:数字、字符串、指针、数组、结构体、以及对应的接口类型。
字典的创建
字典同切片类型一样,属于引用类型,需要使用make
函数或者初始化表达语句来创建。
func main(){
m := make(map[string]int)
m["a"] = 1
m["b"] = 2
m2 := map[int]struct{
x int
}{
1:{x:100},
2:{x:200},
}
fmt.Println(m,m2) // map[a:1 b:2] map[1:{100} 2:{200}]
}
增删改查
func main(){
m := make(map[string]int)
m["a"] = 1
m["b"] = 2
m["c"] = 3 // 新增
m["a"] = 7 // 修改
if v,ok := m["d"];ok{ // 使用ok-idiom模式访问键值对
fmt.Println(v)
}
delete(m,"d") // 删除键值对。不存在时,不会报错
fmt.Println(m) // map[a:7 b:2 c:3]
}
在访问键值对时,如果所访问的键值不存在,不会引发错误,默认会返回零值。但是推荐使用ok-idiom
模式,这样的话就能避免所访问的健对应的值恰好是0,无法判断键值是否存在的情况。
如果对字典进行迭代,那么每次返回的键值顺序都不同。
关于len函数和cap函数
函数len()
返回当前键值对数量,cap()
不接受字典类型。
func main(){
m := make(map[string]int)
m["a"] = 1
m["b"] = 2
fmt.Println(len(m)) // 2
fmt.Println(cap(m)) // invalid argument m (type map[string]int) for cap
}
另外,由于内存访问安全和哈希算法的缘故,字典被设计成not addressable
, 故不能直接修改value
的成员。正确的做法是返回整个value
,修改完成之后再放回。
func main(){
type user struct {
name string
age int
}
m := map[int]user{
1:{"Tom",19},
}
m[1].age += 10 // cannot assign to struct field m[1].age in map
a := m[1]
a.age += 10
m[1] = a
fmt.Println(m) // map[1:{Tom 29}]
}
空字典与nil
内容为空的字典与nil
有所不同,只声明没有初始化的字典为nil
,已初始化没有赋值的字典为空字典,不能对nil
字典进行写操作,但是可以读。
func main(){
a := map[string]int{} // 已经初始化,等同于make操作
var b map[string]int // 只是声明
fmt.Println(a==nil) // false
fmt.Println(b==nil) // true
}