map是对散列表的引用
map的类型是map[k],v, k和v是键和值对应的数据类型。
所有的键拥有相同的数据类型,所有的值也拥有相同的类型。
键的类型k, 必须是可以通过操作符 == 比较的类型。换句话说,键类型的值必须要支持判等操作。由于函数类型、字典类型和切片类型的值并不支持判等操作,所以字典的键类型不能是这些类型。V没有限制。
因为 map 根据 key 来计算 value 的存储位置,如果每次计算相同的key 得出的结果不同,那 dict 内部就完全混乱了。
初始化
ages := make(map[string]int) // mapping from strings to ints
1.
ages := map[string]int{ "alice": 31, "charlie": 34, }
2.
ages := make(map[string]int)
ages["alice"] = 31
ages["charlie"] = 34
另一种创建空的map的表达式是:
map[string]int{}
删除
delete(ages, "alice") // remove element ages["alice"] 第一个参数是map,第二个是键
如果一个查找失败将返回value类型对应的零值,例如,即使map中不存在“bob”下面的代码也可以正常工作,因为ages["bob"]失败时将返回0;
而且x += y和x++等简短赋值语法也可以用在map上,所以上面的代码可以改写成
ages["bob"] += 1
ages["bob"]++
但是map中的元素并不是一个变量,因此我们不能对map的元素进行取址操作:
_ = &ages["bob"] // compile error: cannot take address of map element
禁止对map元素取址的原因是map可能随着元素数量的增长而重新分配更大的内存空间,从而可能导致之前的地址无效。
遍历
for name, age := range ages {
fmt.Printf("%s\t%d\n", name, age)
}
Map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。
如果要按顺序遍历key/value对,我们必须显式地对key进行排序,可以使用sort包的Strings函数对字符串slice进行排序
import "sort"
var names []string
for name := range ages {
names = append(names, name)
}
sort.Strings(names)
for _, name := range names {
fmt.Printf("%s\t%d\n", name, ages[name])
}
map上的大部分操作,包括查找、删除、len和range循环都可以安全工作在nil值的map上,它们的行为和一个空的map类似。但是向一个nil值的map存入元素将导致一个panic异常:
ages["carol"] = 21 // panic: assignment to entry in nil map
有时候可能需要知道对应的元素是否真的是在map之中
age, ok := ages["bob"]
if !ok {
/* "bob" is not a key in this map; age == 0. */
}
if age, ok := ages["bob"]; !ok { /* ... */ }
Map比较
map不可比较(和nil比较除外),为了判断两个map是否拥有相同的键和值,必须写一个循环:
func equal(x,y map[string]int) bool{
if len(x) != len(y){
return false
}
for k,xv := range x{
if yv, ok := y[k]; !ok || yv != xv{
return false
}
}
return true
}
string转map
string本质上是个json串,还是通过json.unmarsha进行转换。
//in := []byte(`{ "votes": { "option_A": "3" } }`) //ok
//in := []byte(`{ votes: { option_A: "3" } }`) //error
in := []byte(`{ "votes": "wer","age":44 }`) //ok
var raw map[string]interface{}
json.Unmarshal(in, &raw)
raw["count"] = 1
out, _ := json.Marshal(raw)
fmt.Println(string(out))