zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Golang 【basic_leaming】map 详解

MapGolang 详解 Basic
2023-09-11 14:14:56 时间

map 的介绍

map 是一种无序的基于 key-value 的数据结构,Go 语言中的 map 是引用类型,必须初始化才能使用。

Go 语言中 map 的定义语法如下:

map[KeyType]ValueType

其中:

KeyType:表示键的类型。
ValueType:表示键对应的值的类型。

map 类型的变量默认初始值为 nil,需要使用 make() 函数来分配内存。

语法为:make: 用于 slice,map,和 channel 的初始化。

make(map[KeyType]ValueType, [cap])

其中 cap 表示 map 的容量,该参数不是必须的。

注意:获取 map 的容量不能使用 cap, cap 返回的是数组切片分配的空间大小, 根本不能用于 map。要获取 map 的容量,可以用len 函数。

map 基本使用

map 中的数据都是成对出现的,map 的基本使用示例代码如下:

package main

import (
	"fmt"
)

func main() {
	scoreMap := make(map[string]int, 8)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100
	fmt.Println(scoreMap)
	fmt.Println(scoreMap["小明"])
	fmt.Printf("type of a:%T\n", scoreMap)
}
PS E:\golang\src> go run .\main.go
map[小明:100 张三:90]
100
type of a:map[string]int
PS E:\golang\src>

map 也支持在声明的时候填充元素,例如:

package main

import (
	"fmt"
)

func main() {
	userInfo := map[string]string{
		"username": "IT 小王子",
		"password": "123456",
	}
	fmt.Println(userInfo)
}
PS E:\golang\src> go run .\main.go
map[password:123456 username:IT 小王子]
PS E:\golang\src>

判断某个键是否存在

Go 语言中有个判断 map 中键是否存在的特殊写法,格式如下:

value, ok := map 对象[key]

举个例子:

package main

import (
	"fmt"
)

func main() {
	scoreMap := make(map[string]int)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100

	// 如果key 存在ok 为true,v 为对应的值;不存在ok 为false,v 为值类型的零值
	v, ok := scoreMap["张三"]
	if ok {
		fmt.Println(v) // 90
	} else {
		fmt.Println("查无此人")
	}
}

map 的遍历

Go 语言中使用 for range 遍历 map。

package main

import (
	"fmt"
)

func main() {
	scoreMap := make(map[string]int)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100
	scoreMap["娜扎"] = 60
	for k, v := range scoreMap {
		fmt.Println(k, v)
	}
}
PS E:\golang\src> go run .\main.go
张三 90
小明 100
娜扎 60
PS E:\golang\src>

但我们只想遍历 key 的时候,可以按下面的写法:

package main

import (
	"fmt"
)

func main() {
	scoreMap := make(map[string]int)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100
	scoreMap["娜扎"] = 60
	for k := range scoreMap {
		fmt.Println(k)
	}
}
PS E:\golang\src> go run .\main.go
小明
娜扎
张三
PS E:\golang\src>

注意: 遍历 map 时的元素顺序与添加键值对的顺序无关。

使用 delete() 函数删除键值对

使用 delete() 内建函数从 map 中删除一组键值对,delete() 函数的格式如下:

delete(map 对象, key)

  • map 对象:表示要删除键值对的 map 对象。
  • key:表示要删除的键值对的键。

示例代码如下:

package main

import (
	"fmt"
)

func main() {
	scoreMap := make(map[string]int)
	scoreMap["张三"] = 90
	scoreMap["小明"] = 100
	scoreMap["娜扎"] = 60
	delete(scoreMap, "小明") // 将小明:100 从map 中删除
	for k, v := range scoreMap {
		fmt.Println(k, v)
	}
}
PS E:\golang\src> go run .\main.go
张三 90
娜扎 60
PS E:\golang\src>

【案例 1】按照指定顺序遍历 map

package main

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano()) //初始化随机数种子
	var scoreMap = make(map[string]int, 200)
	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("stu%02d", i) //生成stu 开头的字符串
		value := rand.Intn(100)          //生成0~99 的随机整数
		scoreMap[key] = value
	}
	//取出map 中的所有key 存入切片keys
	var keys = make([]string, 0, 200)
	for key := range scoreMap {
		keys = append(keys, key)
	}
	//对切片进行排序
	sort.Strings(keys)
	//按照排序后的key 遍历map
	for _, key := range keys {
		fmt.Println(key, scoreMap[key])
	}
}
PS E:\golang\src> go run .\main.go
stu00 2
stu01 83
stu02 27
stu03 19
stu04 87
stu05 22
stu06 64
stu07 94
stu08 14
stu09 3
stu10 13
stu11 75
stu12 64
stu13 81
stu14 60
stu15 57
stu16 29
stu17 80
stu18 97
stu19 43
stu20 54
stu21 21
stu22 36
stu23 73
stu24 92
stu25 9
stu26 97
stu27 30
stu28 36
stu29 38
stu30 71
stu31 50
stu32 50
stu33 45
stu34 39
stu35 26
stu36 4
stu37 89
stu38 91
stu39 59
stu40 7
stu41 68
stu42 11
stu43 13
stu44 29
stu45 63
stu46 80
stu47 2
stu48 59
stu49 66
stu50 68
stu51 91
stu52 39
stu53 84
stu54 55
stu55 11
stu56 95
stu57 48
stu58 70
stu59 66
stu60 95
stu61 34
stu62 26
stu63 51
stu64 89
stu65 89
stu66 24
stu67 63
stu68 46
stu69 82
stu70 67
stu71 86
stu72 71
stu73 80
stu74 55
stu75 4
stu76 48
stu77 73
stu78 21
stu79 65
stu80 69
stu81 85
stu82 90
stu83 8
stu84 41
stu85 70
stu86 49
stu87 97
stu88 72
stu89 55
stu90 95
stu91 98
stu92 66
stu93 15
stu94 88
stu95 67
stu96 73
stu97 37
stu98 33
stu99 79
PS E:\golang\src>

元素为 map 类型的切片

下面的代码演示了切片中的元素为 map 类型时的操作:

package main

import (
	"fmt"
)

func main() {
	var mapSlice = make([]map[string]string, 3)
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}
	fmt.Println("after init")
	// 对切片中的map 元素进行初始化
	mapSlice[0] = make(map[string]string, 10)
	mapSlice[0]["name"] = "小王子"
	mapSlice[0]["password"] = "123456"
	mapSlice[0]["address"] = "海淀区"
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}
}
PS E:\golang\src> go run .\main.go
index:0 value:map[]
index:1 value:map[]
index:2 value:map[]
after init
index:0 value:map[address:海淀区 name:小王子 password:123456]
index:1 value:map[]
index:2 value:map[]
PS E:\golang\src>

值为切片类型的 map

下面的代码演示了 map 中值为切片类型的操作:

package main

import (
	"fmt"
)

func main() {
	var sliceMap = make(map[string][]string, 3)
	fmt.Println(sliceMap)
	fmt.Println("after init")
	key := "中国"
	value, ok := sliceMap[key]
	if !ok {
		value = make([]string, 0, 2)
	}

	value = append(value, "北京", "上海")
	sliceMap[key] = value
	fmt.Println(sliceMap)
}
PS E:\golang\src> go run .\main.go
map[]
after init
map[中国:[北京 上海]]
PS E:\golang\src>

练习题

写一个程序,统计一个字符串中每个单词出现的次数。
比如:”how do you do” 中 how=1 do=2 you=1

package main

import (
	"fmt"
	"strings"
)

func main() {
	var wordMap = make(map[string]int)
	var str = "how do you do"
	var arrSlice = strings.Split(str, " ")
	for _, word := range arrSlice {
		wordMap[word]++
	}
	fmt.Println(wordMap)
}
PS E:\golang\src> go run .\main.go
map[do:2 how:1 you:1]
PS E:\golang\src>