go map类型
hash table 是计算机科学中非常重要的数据结构,它的特性有很多,其中快速查询是最常使用的特性。go 提供了 map 类型,它底层是 hash table。
1. 定义
map 定义形式如下,它分为键(KeyType
)和值(ValueType
),下面例子中m
的KeyType
为string
,ValueType
为int
。
map[KeyType]ValueType
var m map[string]int
map 常用的使用场景是获取 key 对应的值,这就需要判断 map 里面的 key 与用户指定的 key 是否相等,所以 map 要求 KeyType
是可比较的。slice
、map
和函数无法作为 key 。
m["route"] = 66 //将route这个key对应的值设置为66
i := m["route"] //获取route这个key对应的值,并将他赋给i
2. 常用操作
2.1 初始化
仅声明 map 不初始化,map 的值为nil
。当读 nil map 时和读一个空 map 一样,但是写 nil map 时,会抛出异常。
package main
import (
"fmt"
)
func main() {
var m map[string]int
t, ok := m["abc"]
fmt.Printf("\n t is %d, ok is %t", t, ok)
m["def"] = 1
}
提示
当 key 对应的 value 不存在时,map 会返回值类型对应的0值。上面例子里,int
类型的0值为0。
map 的初始化方式有两种:1. 调用内建函数 make
。2. 使用 map literal 。
package main
func main() {
var a map[string]int = make(map[string]int)
var b map[string]int = map[string]int{
"abc": 1,
"def": 2,
}
}
2.2 函数调用
内建函数len
可以返回 map 里面的条目数;delete
方法可以删除 map 里的某一个 key;判断 key 是否存在可以使用二目赋值符;for-range
可以遍历 map 里的键值对。
n := len(m) //获取map里的条目数
delete(m, "route") //删除route对应的值
i, ok := m["route"] //i表示route对应的值,ok表示route是否存在。
for key, value := range m {
fmt.Println("Key:", key, "Value:", value)
}
//遍历m
2.3 值为空接口
空接口类型用interface{}
表示,所有类型都实现了空接口。如果 map 的值类型为interface{}
,意味着值可以是任意类型。
package main
import (
"fmt"
)
func main() {
type FuncType func(s string) string
var c FuncType = func(s string) string {
return s + "funType"
}
d := func(s string) string {
return s + "sfunc"
}
var a map[string]interface{} = map[string]interface{}{
"a": 1,
"b": "kkk",
"c": c,
"d": d,
}
for k, v := range a {
switch vType := v.(type) {
case int:
fmt.Printf("\nkey is %s and value is int %d", k, vType)
case string:
fmt.Printf("\nkey is %s and value is int %s", k, vType)
case FuncType:
fmt.Printf("\nkey is %s and value is int %s", k, vType(k))
case func(s string) string:
fmt.Printf("\nkey is %s and value is int %s", k, vType(k))
}
}
}
2.4 并发访问
map 不是并发安全的,如果在并发的 goroutines 里访问 map 需要进行加锁。例如:
var counter = struct{
sync.RWMutex
m map[string]int
}{m: make(map[string]int)}
counter.RLock() //promoted fields
n := counter.m["some_key"]
counter.RUnlock() //promoted fields
fmt.Println("some_key:", n)
提示
关于 promoted fields 可以参考go 结构体