目录
前言
1、映射的实现
2、元素赋值
3、查找与遍历
4、元素删除
5、将映射传递给函数
前言
映射是一种数据结构,用于存储一系列无序的键值对,映射基于键来存储。
映射功能强大的地方是,能够基于键快速检索数据。键就像索引一样,指向与该键关联的值。
与 C++、java 不一样,Go 使用映射 (map) 不需要引入任何库。
1、映射的实现因为映射也是一个数据集合,所以也可以使用类似处理数组和切片的方式来迭代映射中的元素。但映射是无序集合,所以即使以同样的顺序保存键值对,每次迭代映射时,元素顺序也可能不一样。无序的原因是映射的本质使用了散列表。
map 在底层是用哈希(hash)表实现的,在C:\Program Files\Go\src\hash\maphash\maphash,go,map 是一个 hash 数组列表,由一个个 bucket 组成,示意图如下:
每一个元素都被称为 bucket 的结构体,每一个 bucket 可以保存8个键值对,所有元素被 hash 算法填入到数组的 bucket 中,bucket 填满后,将通过一个 overflow 指针来扩展一个 bucket,从来形成链表,以此来解决 hash 冲突的问题,map 就是一个 bucket 指针型的一维数组。
创建 map 语法如下:
dict := make(map[string]int)
//创建一个映射时,键的类型string,值的类型int
dict := map[string]string{"name":"zhangsan","address":"beijing"}
//创建一个映射时,键、值类型都是string,并对两个键值进行初始化
映射的键可以是任何值,这个值的类型并不限制,内置类型或者结构体都可以,需要确定这个值可以使用 == 运算符做比较。需要注意的是,切片、函数以及包含切片的结构类型由于是引用类型,均不能作为映射的键。
dict := map[[]string]int{}
//报错:incomparable map key type []string
dict := map[int][]string{}
//切片作为值,不可作为键
2、元素赋值
指定适当类型的键并给这个键赋一个值就完成了映射的键值对赋值。
示例:
package main
import "fmt"
//映射赋值
func main() {
colors := map[string]string{}
//赋值直接定义键值对,自动添加
//键名不可以重复,必须唯一
//
colors["red"] = "红色"
colors["bule"] = "蓝色"
colors["bule"] = "蓝"
colors["black"] = "黑"
colors["hei"] = "黑"
colors[""] = "无色"
fmt.Println(colors[""])
fmt.Println(colors["black"])
fmt.Println(colors)
}
//运行结果为:
无色
黑
map[:无色 black:黑 bule:蓝 hei:黑 red:红色]
与切片类似,通过声明一个未初始化的映射可以创建一个值为nil的映射,nil映射不能用于存储键值对,否则,会产生语言运行时错误。
var colors := map[string]string //创建一个nil的映射
colors["red"] = "#da133"
运行报错:
panic: assignment to entry in nil map
goroutine 1 [running]:
3、查找与遍历
从映射取值时有两种方式。
第一种方式:获得值与一个表达这个值是否存在的标志。
package main
import "fmt"
//映射赋值
func main() {
colors := map[string]string{}
//赋值直接定义键值对,自动添加
colors["red"] = "红色"
colors["bule"] = "蓝色"
//第一种方式获取值并且判断值是否存在
value, exe := colors["bule"]
if exe {
fmt.Println(value)
} else {
fmt.Println("不存在")
}
}
//运行结果为:
蓝色
第二种方式:只返回键对应的值,再判断这个值是否有零值,以此来确定键是否存在。这种方式只能用在映射存储的值都是非零值的情况。
package main
import "fmt"
func main() {
//第二种方式获取值
disc := map[string]int{"1": 10, "2": 20, "3": 30}
value := disc["2"]
if value != 0 {
fmt.Println(value)
} else {
fmt.Println("不存在")
}
}
//运行结果为:
20
遍历 map 中所有值。
package main
import "fmt"
func main() {
//遍历map中所有值
disc := map[string]int{"1": 10, "2": 20, "3": 30, "4": 0, "5": 0}
for k, v := range disc {
fmt.Printf("key=%s,value=%d\n", k, v)
}
}
//运行结果为:
key=5,value=0
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=0
4、元素删除
内置函数 delete() 用于删除容器内的元素。
删除格式:
delete(myMap,"1234")
//从myMap中删除键位1234的键对时,如果1234这个键不存在,那么就什么都不发生,也不会有任何副作用。
//但是如果传入的map变量是nil,该调用将导致程序抛出异常(panic)。
示例:
package main
import "fmt"
func main() {
//遍历map中所有值
disc := map[string]int{"1": 10, "2": 20, "3": 30, "4": 0, "5": 0}
for k, v := range disc {
fmt.Printf("key=%s,value=%d\n", k, v)
}
//删除元素
fmt.Println("删除后---------------------------------")
delete(disc, "2")
for k, v := range disc {
fmt.Printf("key=%s,value=%d\n", k, v)
}
}
//运行结果位:
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=0
key=5,value=0
删除后---------------------------------
key=5,value=0
key=1,value=10
key=3,value=30
key=4,value=0
5、将映射传递给函数
在函数间传递映射并不会制造出该映射的副本。当传递映射给函数,并对这个映射做了修改时,所有对这个映射的引用都会察觉到这个修改。
package main
import "fmt"
func main() {
//遍历map中所有值
disc := map[string]int{"1": 10, "2": 20, "3": 30, "4": 0, "5": 0}
for k, v := range disc {
fmt.Printf("key=%s,value=%d\n", k, v)
}
//映射传参处理
fmt.Println("处理后------")
test(disc)
for k, v := range disc {
fmt.Printf("key=%s,value=%d\n", k, v)
}
}
func test(m map[string]int) {
m["4"] = 40
}
//运行结果为:
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=0
key=5,value=0
处理后------
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=40
key=5,value=0
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)