基本操作
package main
import "fmt"
func main() {
aMap := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
k := "two"
v, ok := aMap[k]
if ok {
fmt.Printf("The element of key %q: %d\n", k, v)
} else {
fmt.Println("Not found!")
}
tMap := make(map[int]string)
tMap[1] = "hh"
tMap[2] = "tt"
tMap[3] = "fff"
fmt.Println("tMap: ", tMap)
}
hash table
- Go 语言的字典类型其实是一个哈希表(hash table) 的特定实现
- 而在这个实现中、键和元素最大不同在于,键的类型是受限的、值的类型可以是任意的
- hash table 最重要的一个过程就是: 映射
- 哈希表 会先用哈希函数把 key转为 hash值、hash value 通常是一个无符号的整数
- 一个hash table 会持有一定数量的 bucket、这些bucket也可以叫 哈希桶、这里存储了真正的键值对
- 只要键值对在hash表中、那么就一定会被找到
映射
- 把 key转为 hash值, 字典不会独立存储任何键的值、但会独立存储他们的哈希值
- Go语言 字典的 键类型不能是 函数、字典、切片等类型
为什么 键类型不能是 函数、字典、切片等类型?
- Go 语言规范规定、在键类型的值之间 必须可以施加 == 和 !=
- 也就是说 Go语言 map 键类型必须要支持 判等操作,所以字典的键类型不能是这些类型
- 如果 键的类型是接口类型的,那么键值的实际类型也不能是 这三种类型、否则会panic
var badMap2 = map[interface{}]int{
"1": 1,
[]int{2}: 2, // 这里会引发panic。语法层面可以、运行时不行
3: 3,
}
应该优先考虑哪些类型作为 map的 key类型?
- 性能上来说 把键值转换为 hash值 和 查找的键值与哈希桶中的键值作对比、这两个操作耗时
- 因此、求哈希 和 判等操作速度越快、对应的类型就越适合作为键类型
- 宽度越小的类型 求hash的操作就越快、这里宽度指的是单个值需要占的字节数。
- bool、int8、uint8 类型都是占用一个字节
一个map是nil、对它进行读操作会成功、写操作会成功吗?
- 由于字典是引用类型、所以当我们仅声明而不初始化字典时、它的值是nil
- 对一个为nil的字典进行 写操作的时候 会引起运行时 panic
- 除了添加操作、其他操作都不会失败
map 并发安全吗?
源码解析
图解