「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
概念
- 中文叫映射,感觉就是 Python 的 dict 字典,是一种无序的键值对的集合
- 映射是方便而强大的内建数据结构,它可以关联不同类型的值
map 的特点
- map 是无序的,每次打印出来的 map 都会不一样,它不能通过 index 获取,而必须通过 key 获取
- map 的长度是不固定的,这是因为 map 是使用 hash 表来实现的
- map 和 slice 一样,是一种引用类型,也可以像迭代数组和切片那样迭代它
- 内置的 len 函数同样适用于 map,返回 map 拥有的 key 的数量
- map 的 key 可以是所有可比较的类型,整数、浮点数、复数、字符串、指针、接口(只要其动态类型支持相等性判断)、结构以及数组,但切片不能用作映射键,因为它们的相等性还未定义
创建 map
package main
import "fmt"
func main() {
// 有初始数据
var timeZone = map[string]int{
"UTC": 0 * 60 * 60,
"EST": -5 * 60 * 60,
"CST": -6 * 60 * 60,
"MST": -7 * 60 * 60,
"PST": -8 * 60 * 60,
}
intMap := map[int]int{
1: 123,
2: 112233,
3: 111222333,
}
fmt.Println(timeZone, intMap)
}
运行结果
map[CST:-21600 EST:-18000 MST:-25200 PST:-28800 UTC:0] map[1:123 2:112233 3:111222333]
map 的默认值是 nil
nil 映射既没有键,也不能添加键值对,如果添加会报错,需要通过 make 来添加
package main
import "fmt"
func main() {
var strMap map[string]string
fmt.Printf("%T, %v, %v \n", strMap, strMap, len(strMap))
// 下面代码会报错
strMap["name"] = "小菠萝测试"
strMap["age"] = "24"
}
运行结果
map[string]string, map[], 0
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/tmp/sandbox3315044160/prog.go:9 +0x9f
Program exited.
使用 make 创建
package main
import "fmt"
func main() {
// 一行代码创建一个空 map
strMap := make(map[string]string)
strMap["name"] = "小菠萝测试"
strMap["age"] = "24"
fmt.Println( strMap, strMap["name"])
}
运行结果
map[age:24 name:小菠萝测试] 小菠萝测试
for 循环读取 map
用 range 形式去循环读取 map 的时候,第一个值是 key,第二个值是 value
package main
import "fmt"
func main() {
// 一行代码创建
var timeZone = map[string]int{
"UTC": 0 * 60 * 60,
"EST": -5 * 60 * 60,
"CST": -6 * 60 * 60,
"MST": -7 * 60 * 60,
"PST": -8 * 60 * 60,
}
for key := range timeZone {
fmt.Println(timeZone[key])
}
}
运行结果
0
-18000
-21600
-25200
-28800
双赋值检测键是否存在
- 读取 map 的 key 时会返回两个值
- 第一个值就是 key 对应的 value
- 第二个值是布尔值,如果 key 存在则 true,不存在则 false,可以根据这个值来做条件判断
- 如果 key 不存在,则会返回 value 对应类型的零值,
package main
import "fmt"
func main() {
// 一行代码创建
var timeZone = map[string]int{
"UTC": 0 * 60 * 60,
"EST": -5 * 60 * 60,
"CST": -6 * 60 * 60,
"MST": -7 * 60 * 60,
"PST": -8 * 60 * 60,
}
value, ok := timeZone["CST"]
fmt.Printf("%v, %v \n", value, ok)
value, ok = timeZone["NO"]
fmt.Printf("%v, %v", value, ok)
}
运行结果
-21600, true
0, false
条件判断
跟着上面的🌰 ,将读取 map[key] 封装成一个函数
package main
import (
"fmt"
"log"
)
func main() {
// 条件判断
var timeZone = map[string]int{
"UTC": 0 * 60 * 60,
"EST": -5 * 60 * 60,
"CST": -6 * 60 * 60,
"MST": -7 * 60 * 60,
"PST": -8 * 60 * 60,
}
fmt.Println(offset(timeZone, "CST"))
offset(timeZone, "NO")
}
func offset(myMap map[string]int, key string) int {
if value, ok := myMap[key]; ok {
return value
}
log.Println("unknown time zone:", key)
return 0
}
运行结果
-21600
2009/11/10 23:00:00 unknown time zone: NO
map 是引用类型,指针传递
- 前面说了,map 和切片类似,都是引用类型
- 当不同变量指向同一个 map 的时候,通过不同变量修改 map 的值,会影响其他变量
🌰 一:多个变量指向同一个 map
package main
import "fmt"
func main() {
map1 := map[string]string{
"France": "1",
"Italy": "2",
"Japan": "3",
"India": "4",
}
map2 := map1
fmt.Println(map1, map2)
map2["China"] = "5"
delete(map1, "India")
fmt.Println(map1, map2)
}
运行结果
map[France:1 India:4 Italy:2 Japan:3] map[France:1 India:4 Italy:2 Japan:3]
map[China:5 France:1 Italy:2 Japan:3] map[China:5 France:1 Italy:2 Japan:3]
🌰 二:map 作为函数的参数
package main
import "fmt"
func main() {
myMap := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
fmt.Println(myMap)
addMap(myMap)
fmt.Println(myMap)
}
func addMap(myMap map[string]int) {
myMap["func"] = 2
myMap["ok"] = 1
}
运行结果
map[a:1 b:2 c:3]
map[a:1 b:2 c:3 func:2 ok:1]
map 不能使用 == 操作符进行比较
==只能用来检查map是否为空
package main
import "fmt"
func main() {
map1 := map[string]string{
"France": "1",
"Italy": "2",
}
map2 := map1
fmt.Println(map1 == map2)
}
运行结果
./prog.go:15:19: invalid operation: map1 == map2 (map can only be compared to nil)