定义与操作
定义与操作
我们看下面的代码,map 的读取和设置也类似 slice 一样,通过 key 来操作,只是 slice 的 index 只能是 int 类型,而 map 多了很多类型,可以是 int,可以是 string 及所有完全定义了 ==
与 !=
操作的类型。
// 声明一个 key 是字符串,值为int的字典,这种方式的声明需要在使用之前使用make初始化
var numbers map[string]int
// 另一种 map 的声明方式
numbers := make(map[string]int)
numbers := map[string]int{}
// map 中的默认值为 0
numbers["one"] = 1//赋值
numbers["ten"] = 10 //赋值
numbers["three"] = 3
fmt.Println("第三个数字是: ", numbers["three"]) // 读取数据
// 打印出来如:第三个数字是: 3
这个 map 就像我们平常看到的表格一样,左边列是 key,右边列是值,使用 map 过程中需要注意的几点:
- map 是无序的,每次打印出来的 map 都会不一样,它不能通过 index 获取,而必须通过 key 获取
- map 的长度是不固定的,也就是和 slice 一样,也是一种引用类型
- 内置的 len 函数同样适用于 map,返回 map 拥有的 key 的数量
- map 的值可以很方便的修改,通过
numbers["one"]=11
可以很容易的把 key 为one
的字典值改为11
- map 和其他基本型别不同,它不是 thread-safe,在多个 go-routine 存取时,必须使用 mutex lock 机制
特别注意的是,map 也是一种引用类型,如果两个 map 同时指向一个底层,那么一个改变,另一个也相应的改变:
m := make(map[string]string)
m["Hello"] = "Bonjour"
m1 := m
m1["Hello"] = "Salut"// 现在m["hello"]的值已经是Salut了
取值与遍历
对 map 取值,返回两个参数,第二个参数为 bool 值,标志 key 是否存在于 map 中:
s := m["hello"] // 如果key不存在,s为对应类型的零值
s, ok := m["hello"] // 如果key不存在, ok为false,反之为true
_, exists := m["hello"] // 用来确定key是否存在
map 的零值为 nil。对于 map 的零值得读取,不会出错,但是写入则会引发 panic,例如:
func main() {
var m map[string]string
fmt.Println(m["hello"])
m["hello"] = "world"
}
// error
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/tmp/main.go:10 +0xee
exit status 2
操作
删除
通过delete
删除 map 的元素:
// 初始化一个字典
rating := map[string]float32{"C":5, "Go":4.5, "Python":4.5, "C++":2 }
// map有两个返回值,第二个返回值,如果不存在key,那么ok为false,如果存在ok为true
csharpRating, ok := rating["C#"]
if ok {
fmt.Println("C# is in the map and its rating is ", csharpRating)
} else {
fmt.Println("We have no rating associated with C# in the map")
}
delete(rating, "C")// 删除key为C的元素