package mainimport ("fmt"
)/*
输出:
这个元素key "one":1
*/
func main() {aMap := map[string]int{"one": 1,"two": 2,"three": 3,}k := "one"v, ok := aMap[k]if ok {fmt.Printf("这个元素key %q:%d\n", k, v)} else {fmt.Println("没有发现!")}
}
键类型的值必须支持判等操作(可以施加操作符==和!=)。由于函数类型、字典类型、切片类型,不支持判等操作,所以字典的键类型不能是这些类型。
package mainimport ("fmt"
)/*
引起恐慌的示例
*/
func main() {var badMap2 = map[interface{}]int{"1": 1,3: 3,[]int{2}: 2, // panic: runtime error: hash of unhashable type []int}fmt.Println(badMap2)
}
上面的代码,编译时不会出错。因为通过接口类型躲过了Go语言编译器的检查。
最好,不要把字典的键类型设定为任何接口类型。
求哈希和判等操作的速度越快,对应的类型就越适合作为键类型。
对于所有的基本类型、指针类型、以及数组类型、结构体类型和接口类型。Go语言都有一套算法与之对应。这套算法中就包含了哈希和判等。
以求哈希值为例,宽度越小的类型速度通常越快。对于字符串类型,由于它的宽度是不定的,所以要看它的值的具体长度,长度越短求哈希越快。
类型的宽度是指单个值需要占用的字节数。
对于高级类型:
不建议使用高级类型作为字典的键类型。(因为对它们的值求哈希,以及判等的速度较慢。)
建议优先选用数值类型和指针类型作为键类型。
package mainimport "fmt"func main() {var m map[string]int// m = map[string]int{} // 补充上这句话,下面的执行就不会引起恐慌了fmt.Println(m)key := "one"v01, ok := m[key] // 不会引起恐慌fmt.Printf("在值为nil的map中获取key为 %q 的值:%d,%v\n", key, v01, ok)fmt.Printf("map的长度为:%d\n", len(m))fmt.Printf("在值为nil的map上删除key为 %q\n", key)delete(m, key) // 不会引起恐慌fmt.Println("向值为nil的map上添加一个元素,会引起恐慌")m[key] = 2
}
非原子操作需要加锁, map并发读写需要加锁,map操作不是并发安全的,判断一个操作是否是原子的可以使用 go run race 命令做数据的竞争检测。