映射(map)
映射是一种数据结构,用于存储一系列无序的键值对,映射基于键来存值,能够快速检索数据。键就像索引一样,指向与该键关联的值。
映射的实现
Go语言中 map 的底层是哈希(hash)表实现的,它的源码在 $GOROOT/src/pkg/runtime/hashmap.go/
可以查看它的实现细节。Go语言的 map 是一个数组列表,不是像 C++ 一样使用红黑树,与传统的 hashmap 一样,Go语言的 map 由一个个 bucket 组成。在这个数组列表中的每一个元素都被称为 bucket 的结构体,每个 bucket 可以保存为 8 个键值对,所有元素将被 hash 算法填入到数组的 bucket 中;当 bucket 填满后,会使用一个 overflow 指针来扩展一个 bucket ,从而形成链表,以此解决 hash 冲突的问题。
映射的创建和初始化
- 使用make函数创建映射
- 使用映射字面量(常用)
func main(){ //使用make函数创建映射 a1 := make(map[string]int) fmt.Println(a1) //打印零值 //使用映射字面量初始化 a1 = map[string]int{"Cat":1,"Dog":2,"Bee":3} fmt.Println(a1)}/*map[]map[Bee:3 Cat:1 Dog:2]*/
使用映射字面量初始化是常用的方法,映射的初始长度会根据初始化时指定的键值对的数量来确定。映射的键可以是任何类型的值,内置类型或者结构类型都可以,不过需要确定这个值可以用 == 比较运算符做比较。需要注意的是,切片、函数以及包含切片结构类型由于具有引用语义,所以这些数据类型都不能用作映射的键,编译器会报错:
//创建一个映射,使用字符串切片作为映射的键func main(){ dict := map[[]string]int{} fmt.Println(dict)}/*command-line-argumentsinvalid map key type []string*/
但是可以使用切片作为映射的值
//创建一个映射,使用字符串切片作为映射的值func main(){ dict := map[int][]string{} fmt.Println(dict)}/*map[]*/
映射的使用
元素赋值
通过指定适当类型的键并给这个键赋值就完成了映射的键值对赋值。
func main(){ //使用空字面量创建初始化后的空映射 dict := map[string]int{} fmt.Println(dict) //映射赋值 dict["Star"] = 1 fmt.Println(dict) //使用make函数创建初始化后的空映射 dict1 := make(map[string]int) fmt.Println(dict1) //映射赋值 dict1["Moon"] = 2 fmt.Println(dict1)}/*map[]map[Star:1]map[]map[Moon:2]*/
声明一个未初始化的映射可以产生值为 nil 的映射。nil 映射不能用于存储键值对,否则编译器会抛出panic异常。
func main(){ //创建一个未初始化的空映射,值为 nil var dict map[string]int //nil 映射赋值 dict["Star"] = 1 fmt.Println(dict)}/*panic: assignment to entry in nil map*/
映射的查找和遍历
映射取值有两种方式:
- 先获取对应键的值,再判断是否存在,若存在则打印值,若不存在则什么也不做
- 先取取对应键的值,再判断值是否为零值 (如果非空,说明存在;如果为空,说明不存在)
func main() { //使用字面量创建初始化后的映射 dict := map[string]int{"Cat": 1, "Dog": 2, "Bee": 3} //方法一:映射取值,获得键对应的值 value, exists := dict["Dog"] if exists { fmt.Println(value) } //方法二:先取对应键的值,再判断值是否为零值 如果非空,说明存在;如果为空,说明不存在 value = dict["Cat"] if value != 0 { fmt.Println(value) }}/*21*/
在Go语言里,通过键来索引映射时,即便这个键不存在,也会返回该值对应类型的零值。
映射遍历
func main() { //使用字面量创建初始化后的映射 dict := map[string]int{"Cat": 1, "Dog": 2, "Bee": 3} //映射遍历 for i,v := range dict { fmt.Println(i,v) }}/*Cat 1Dog 2Bee 3*/
元素删除
Go语言里提供了内置函数 delete() 用于删除容器内的元素。
func main() { //使用字面量创建初始化后的映射 dict := map[string]int{"Cat": 1, "Dog": 2, "Bee": 3} fmt.Println(dict) //删除元素 delete(dict,"Cat") fmt.Println(dict)}/*map[Bee:3 Cat:1 Dog:2]map[Bee:3 Dog:2]*/
将映射传递给函数
在函数间传递映射并不会制造出该映射的一个副本
func main() {// 创建一个映射,存储颜色以及颜色对应的十六进制代码myColors := map[string]string{"AliceBlue":"#f0f8ff","Coral":"#ff7F50","DarkGray":"#a9a9a9","ForestGreen": "#228b22",}// 显示映射里的所有颜色for key, value := range myColors {fmt.Printf("Key: %s Value: %s\n", key, value)}fmt.Println()// 调用函数来移除指定的键removeColor(myColors, "Coral")// 显示映射里的所有颜色for key, value := range myColors {fmt.Printf("Key: %s Value: %s\n", key, value)}}// removeColor 将指定映射里的键删除func removeColor(colors map[string]string, key string) {delete(colors, key)}/*Key: AliceBlue Value: #f0f8ffKey: Coral Value: #ff7F50Key: DarkGray Value: #a9a9a9Key: ForestGreen Value: #228b22Key: AliceBlue Value: #f0f8ffKey: DarkGray Value: #a9a9a9Key: ForestGreen Value: #228b22*/
文章来源:智云一二三科技
文章标题:Golang 复合数据类型:映射
文章地址:https://www.zhihuclub.com/3453.shtml