Golang入门笔记-CH06-Map

  1. 声明和初始化 Map
  2. Map 容量
  3. 判断键值对是否存在
  4. 删除元素
  5. 遍历 Map
  6. Map 类型的切片

声明和初始化 Map

map 是一种特殊的数据结构,通过键 key 和值 value 来保存数据,可以快速地根据 key 找到其对应的 value,与 python 中的字典和 Java 中的 HashMap 类似。

map引用类型,声明方式如下:

1
var variable map[keyType]valueType

在声明的时候不需要知道 map 的长度,map 是可以动态增长的。

未初始化的 map 的值是 nil

map 中的 key 只能是可以用 ==!= 来比较的变量类型,例如 stringintfloat 等,不能是数组,结构体和切片,但指针和接口可以作为 key。如果要使用结构体来作为 key,需要提供 Key()Hash() 方法,value 可以为任意类型。

可以通过赋值符号来设置 key1 对应的 value

1
map1[key1] = value

也可以根据赋值符号获取 key1 对应的 value,若 map1 中没有 key1 对应的值,val 将会被赋值 map1 的值类型的空值。

1
val := map1[key1]

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import "fmt"

func main() {
var mapLit map[string]int
var mapAssigned map[string]int

mapLit = map[string]int{"one": 1, "two": 2}
mapCreated := make(map[string]float32)
mapAssigned = mapLit

mapCreated["key1"] = 4.5
mapCreated["key2"] = 3.14159
mapAssigned["two"] = 3

fmt.Printf("Map literal at \"one\" is: %d\n", mapLit["one"])
fmt.Printf("Map created at \"key2\" is: %f\n", mapCreated["key2"])
fmt.Printf("Map assigned at \"two\" is: %d\n", mapLit["two"])
fmt.Printf("Map literal at \"ten\" is: %d\n", mapLit["ten"])
}

上述代码运行结果为:

1
2
3
4
Map literal at "one" is: 1
Map created at "key2" is: 3.14159
Map assigned at "two" is: 3
Mpa literal at "ten" is: 0

可以用 {key1: val1, key2: val2} 来初始化 map

map 是引用类型,因此用 make 来分配内存。

map 的常规初始化方式:

1
var map1[keyType]valueType = make(map[keyType]valueType)

也可以简写为:

1
map1 := make(map[keyType]valueType)

mapCreated := make(map[string]float) 相当于:mapCreated := map[string]float{}

Map 容量

map 会动态扩容,因此它不存在长度限制。但也可以在初始化 map 时指定它的初始容量,格式如下:

1
map1 := make(map[string]int, 100) // map1 的初始容量为 100

map 增长到最大容量时,容量会自动加 1。但对于性能要求较高的场景,若 map 中保存的数据较多或易快速扩张,建议在初始化时指定其初始容量。

判断键值对是否存在

我们可以通过如下的格式来判断 map 中的 key 是否存在:

1
val, ok := map1[key]

ok 的值为 true,则表明该 key 存在,否则不存在。

若只是想判断 key 是否存在,而不需要获取 key 对应的 value,可以这样写:

1
_, ok := map1[key]

还可以和 if 混用:

1
2
3
if _, ok := map1[key]; ok {
// ...
}

删除元素

删除 map 中的元素,可以通过 delete 函数,如删除 map1key 对应的元素:

1
delete(map1, key)

即使要删除的 key 不存在,也不会报错。

遍历 Map

可以通过 for range 循环来遍历 map

1
2
3
for key, value := range map1 {
// ...
}

如果只需遍历 map 中的 value,可以用匿名变量来接收 key

1
2
3
for _, value := range map1 {
// ...
}

如果只需要遍历 mapkey,可以省略 value

1
2
3
for key := range map1 {
// ...
}

我们来看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"

func main() {
map1 := make(map[int]float32)
map1[1] = 1.0
map1[2] = 2.0
map1[3] = 3.0
map1[4] = 4.0
for key, value := range map1 {
fmt.Printf("key is: %d - value is: %f\n", key, value)
}
}

上述代码运行结果为:

1
2
3
4
key is: 3 - value is: 3.000000
key is: 1 - value is: 1.000000
key is: 4 - value is: 4.000000
key is: 2 - value is: 2.000000

注意map 中元素不是按照 key 来排序的。

Map 类型的切片

如果我们要创建一个 map 类型的切片,一定要使用两次 make() 函数,第一次分配切片的内存,第二次分配 map 的内存。

来看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import "fmt"

func main() {
// Version A:
items := make([]map[int]int, 5)
for i:= range items {
items[i] = make(map[int]int, 1)
items[i][1] = 2
}
fmt.Printf("Version A: Value of items: %v\n", items)

// Version B: NOT GOOD!
items2 := make([]map[int]int, 5)
for _, item := range items2 {
item = make(map[int]int, 1) // item 仅仅是切片 items2 元素的拷贝
item[1] = 2
}
fmt.Printf("Version B: Value of items: %v\n", items2)
}

运行结果为:

1
2
Version A: Value of items: [map[1:2] map[1:2] map[1:2] map[1:2] map[1:2]]
Version B: Value of items: [map[] map[] map[] map[] map[]]

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 richffan@outlook.com

文章标题:Golang入门笔记-CH06-Map

字数:1.1k

本文作者:Rich Fan

发布时间:2022-10-01, 00:00:00

最后更新:2024-02-27, 08:17:39

原始链接:http://fanrich.github.io/2022/09/30/Golang/Golang%E5%85%A5%E9%97%A8%E7%AC%94%E8%AE%B0-CH06-Map/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。