mirror of
https://gitee.com/shikong-sk/golang-study
synced 2025-02-23 23:42:15 +08:00
400 lines
8.5 KiB
Markdown
400 lines
8.5 KiB
Markdown
|
**
|
|||
|
本章目录:**
|
|||
|
|
|||
|
- 0x02 Go语言基础之Map映射
|
|||
|
|
|||
|
- - 1.Map 声明定义
|
|||
|
- 2.Map 基础使用
|
|||
|
- 3.Map 键值遍历
|
|||
|
- 4.Map 键值删除
|
|||
|
- 5.值为map类型的切片
|
|||
|
- 6.值为切片类型的map
|
|||
|
- 7.示例演示
|
|||
|
|
|||
|

|
|||
|
|
|||
|
# 0x02 Go语言基础之Map映射
|
|||
|
|
|||
|
描述: Go语言中提供的映射关系容器为map, 其内部使用散列表(hash)实现。
|
|||
|
|
|||
|
# 1.Map 声明定义
|
|||
|
|
|||
|
描述: Map 是一种无序的基于`key-value`的数据结构, 并且它是引用类型,所以必须初始化值周才能进行使用。
|
|||
|
|
|||
|
**语法定义:**
|
|||
|
|
|||
|
```javascript
|
|||
|
map[KeyType]ValueType
|
|||
|
|
|||
|
// # 参数说明:
|
|||
|
- KeyType:表示键的类型。
|
|||
|
- ValueType:表示键对应的值的类型。
|
|||
|
```
|
|||
|
|
|||
|
Tips : map类型的变量`默认初始值为nil`,需要使用`make()函数来分配内存`。语法为:`make(map[KeyType]ValueType, [cap])`, 其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# 2.Map 基础使用
|
|||
|
|
|||
|
描述:Map 中的数据都是成对出现的其Map的基本使用示例代码如下:
|
|||
|
|
|||
|
```go
|
|||
|
// 1.采用Make初始化Map类型的变量。
|
|||
|
scoreMap := make(map[string]int, 8)
|
|||
|
scoreMap["小明"] = 100
|
|||
|
fmt.Println(scoreMap["小明"])
|
|||
|
fmt.Printf("type of a:%T\n", scoreMap)
|
|||
|
|
|||
|
// 2.在声明时填充元素。
|
|||
|
userInfo := map[string]string{
|
|||
|
"username": "WeiyiGeek",
|
|||
|
"password": "123456",
|
|||
|
}
|
|||
|
fmt.Println(userInfo)
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# 3.Map 键值遍历
|
|||
|
|
|||
|
描述: 在进行Map类型的变量遍历之前,我们先学习判断map中键是否存在。
|
|||
|
|
|||
|
**(1) 键值判断**
|
|||
|
描述: 判断Map中某个键是否存在可以采用如下特殊写法: `value, ok := map[key]`
|
|||
|
|
|||
|
```go
|
|||
|
scoreMap := make(map[string]int)
|
|||
|
scoreMap["小明"] = 100
|
|||
|
value, ok := scoreMap["张三"]
|
|||
|
if ok {
|
|||
|
fmt.Println("scoreMap 存在该 '张三' 键")
|
|||
|
} else {
|
|||
|
fmt.Println("scoreMap 不存在该键值")
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
**(2) 键值遍历**
|
|||
|
描述: Go 语言中不像Python语言一样有多种方式进行遍历, 大道至简就 `for...range` 遍历 `Map` 就可以搞定。
|
|||
|
|
|||
|
```go
|
|||
|
scoreMap := make(map[string]int)
|
|||
|
scoreMap["Go"] = 90
|
|||
|
scoreMap["Python"] = 100
|
|||
|
scoreMap["C++"] = 60
|
|||
|
// 遍历 k-v 写法
|
|||
|
for k, v := range scoreMap {
|
|||
|
fmt.Println(k, v)
|
|||
|
}
|
|||
|
|
|||
|
// 遍历 k 写法
|
|||
|
for k := range scoreMap {
|
|||
|
fmt.Println(k)
|
|||
|
}
|
|||
|
|
|||
|
// 遍历 v 写法
|
|||
|
for _, v := range scoreMap {
|
|||
|
fmt.Println(v)
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Tips :遍历map时的元素顺序与添加键值对的顺序无关。
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# 4.Map 键值删除
|
|||
|
|
|||
|
描述: 我们可使用 `delete() 内建函数` 从map中删除一组键值对, `delete()` 函数的格式如下: `delete(map, key)`
|
|||
|
|
|||
|
其中 `map:`表示要删除键值对的map, `key:` 表示要删除的键值对的键。
|
|||
|
|
|||
|
```go
|
|||
|
scoreMap := make(map[string]int)
|
|||
|
scoreMap["张三"] = 90
|
|||
|
scoreMap["小明"] = 100
|
|||
|
delete(scoreMap, "小明" ) // 将`小明:100`从map中删除
|
|||
|
for k,v := range scoreMap{
|
|||
|
fmt.Println(k, v)
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# 5.值为map类型的切片
|
|||
|
|
|||
|
描述: 第一次看到时可能比较绕,其实可以看做在切片中存放Map类型变量。
|
|||
|
|
|||
|
简单示例:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
```go
|
|||
|
func demo3() {
|
|||
|
var mapSlice = make([]map[string]string, 3)
|
|||
|
for index, value := range mapSlice {
|
|||
|
fmt.Printf("index:%d value:%v\n", index, value)
|
|||
|
}
|
|||
|
fmt.Println()
|
|||
|
// 对切片中的map元素进行初始化
|
|||
|
mapSlice[0] = make(map[string]string, 10)
|
|||
|
mapSlice[1] = make(map[string]string, 10)
|
|||
|
mapSlice[2] = make(map[string]string, 10)
|
|||
|
mapSlice[0]["name"] = "WeiyiGeek"
|
|||
|
mapSlice[0]["sex"] = "Man"
|
|||
|
mapSlice[1]["姓名"] = "极客"
|
|||
|
mapSlice[1]["性别"] = "男"
|
|||
|
mapSlice[2]["hobby"] = "Computer"
|
|||
|
mapSlice[2]["爱好"] = "电脑技术"
|
|||
|
for i, v := range mapSlice {
|
|||
|
//fmt.Printf("index:%d value:%v\n", i, v)
|
|||
|
for _, value := range v {
|
|||
|
fmt.Printf("index:%d value:%v\n", i, value)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
执行结果:
|
|||
|
|
|||
|
```go
|
|||
|
index:0 value:map[]
|
|||
|
index:1 value:map[]
|
|||
|
index:2 value:map[]
|
|||
|
|
|||
|
index:0 value:Man
|
|||
|
index:0 value:WeiyiGeek
|
|||
|
index:1 value:极客
|
|||
|
index:1 value:男
|
|||
|
index:2 value:Computer
|
|||
|
index:2 value:电脑技术
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# 6.值为切片类型的map
|
|||
|
|
|||
|
描述: 同样在Map中存放切片类型的数据。
|
|||
|
|
|||
|
代码演示了map中值为切片类型的操作:
|
|||
|
|
|||
|
```go
|
|||
|
// 值为切片类型的map
|
|||
|
func demo4() {
|
|||
|
var sliceMap = make(map[string][]string, 3)
|
|||
|
var key = [2]string{"Country", "City"}
|
|||
|
fmt.Println("初始化 sliceMap 其值 : ", sliceMap)
|
|||
|
|
|||
|
for _, v := range key {
|
|||
|
// 判断键值是否存在如果不存在则初始化一个容量为2的切片
|
|||
|
value, ok := sliceMap[v]
|
|||
|
if !ok {
|
|||
|
value = make([]string, 0, 2)
|
|||
|
}
|
|||
|
if v == "Country" {
|
|||
|
value = append(value, "中国", "台湾")
|
|||
|
} else {
|
|||
|
value = append(value, "北京", "上海")
|
|||
|
}
|
|||
|
// 将切片值赋值给Map类型的变量
|
|||
|
sliceMap[v] = value
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
执行结果:
|
|||
|
|
|||
|
```go
|
|||
|
初始化 sliceMap 其值 : map[]
|
|||
|
map[City:[北京 上海] Country:[中国 台湾]]
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Tips : 非常重要、重要 `Slice切片与Map` 在使用时一定要做初始化操作(在内存空间申请地址)。
|
|||
|
|
|||
|
|
|||
|
|
|||
|
# 7.示例演示
|
|||
|
|
|||
|
**1.Map类型的基础示例**
|
|||
|
|
|||
|
```go
|
|||
|
func demo1() {
|
|||
|
// 1.Map 定义
|
|||
|
var a1 map[string]int8 // (未分配内存)
|
|||
|
fmt.Println("Map 类型 的 a1 变量 :", a1)
|
|||
|
if a1 == nil {
|
|||
|
fmt.Println("默认初始化的Map类型的a1变量值: nil")
|
|||
|
}
|
|||
|
|
|||
|
// 2.基本使用利用Make进行分配内存空间存储Map。
|
|||
|
b1 := make(map[string]string, 8)
|
|||
|
b1["姓名"] = "WeiyiGeek"
|
|||
|
b1["性别"] = "男|man"
|
|||
|
b1["爱好"] = "计算机技术"
|
|||
|
b1["出生日期"] = "2021-08-08"
|
|||
|
// 指定输出
|
|||
|
fmt.Printf("b1['姓名'] = %v \n", b1["姓名"])
|
|||
|
// 整体输出
|
|||
|
fmt.Printf("Map b1 Type: %T , Map b1 Value: %v \n", b1, b1)
|
|||
|
|
|||
|
// 3.在声明时填充元素。
|
|||
|
c1 := map[string]string{
|
|||
|
"username": "WeiyiGeek",
|
|||
|
"sex": "Man",
|
|||
|
"hobby": "Computer",
|
|||
|
}
|
|||
|
// 指定输出
|
|||
|
fmt.Printf("c1['username'] = %v \n", c1["username"])
|
|||
|
// 整体输出
|
|||
|
fmt.Printf("Map c1 Type: %T , Length : %d , Map c1 Value: %v \n", c1, len(c1), c1)
|
|||
|
|
|||
|
// 4.判断c1中的键值时候是否存在 sex Key.
|
|||
|
value, ok := c1["sex"]
|
|||
|
if ok {
|
|||
|
fmt.Println("c1 Map 变量中存在 'sex' 键 = ", value)
|
|||
|
} else {
|
|||
|
fmt.Println("c1 Map 变量中不存在 sex 键")
|
|||
|
}
|
|||
|
|
|||
|
// 5.遍历Map
|
|||
|
for k, v := range b1 {
|
|||
|
fmt.Println(k, "=", v)
|
|||
|
}
|
|||
|
|
|||
|
// 6.删除指定键值对,例如删除c1中的hobby键值。
|
|||
|
delete(c1, "hobby")
|
|||
|
fmt.Printf("Map 现存在的键 : ")
|
|||
|
for k := range c1 {
|
|||
|
fmt.Print(k, " ")
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
执行结果:
|
|||
|
|
|||
|
```go
|
|||
|
Map 类型 的 a1 变量 : map[]
|
|||
|
默认初始化的Map类型的a1变量值: nil
|
|||
|
b1['姓名'] = WeiyiGeek
|
|||
|
Map b1 Type: map[string]string , Map b1 Value: map[出生日期:2021-08-08 姓名:WeiyiGeek 性别:男|man 爱好:计算机技术]
|
|||
|
c1['username'] = WeiyiGeek
|
|||
|
Map c1 Type: map[string]string , Length : 3 , Map c1 Value: map[hobby:Computer sex:Man username:WeiyiGeek]
|
|||
|
c1 Map 变量中存在 'sex' 键 = Man
|
|||
|
出生日期 = 2021-08-08
|
|||
|
姓名 = WeiyiGeek
|
|||
|
性别 = 男|man
|
|||
|
爱好 = 计算机技术
|
|||
|
Map 现存在的键 : username sex
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
**2.按照指定顺序遍历map**
|
|||
|
|
|||
|
```go
|
|||
|
func demo2() {
|
|||
|
rand.Seed(time.Now().UnixNano()) //初始化随机数种子
|
|||
|
|
|||
|
// 申请并初始化一个长度为 200 的 Map
|
|||
|
var scoreMap = make(map[string]int, 200)
|
|||
|
for i := 0; i < 20; 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])
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
执行结果:
|
|||
|
|
|||
|
```go
|
|||
|
stu00 4
|
|||
|
stu01 48
|
|||
|
stu02 66
|
|||
|
stu03 18
|
|||
|
stu04 13
|
|||
|
stu05 89
|
|||
|
stu06 80
|
|||
|
stu07 16
|
|||
|
stu08 11
|
|||
|
stu09 26
|
|||
|
stu10 42
|
|||
|
stu11 45
|
|||
|
stu12 24
|
|||
|
stu13 47
|
|||
|
stu14 92
|
|||
|
stu15 77
|
|||
|
stu16 12
|
|||
|
stu17 16
|
|||
|
stu18 17
|
|||
|
stu19 76
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Tips : 探究上述示例中`Array 数组、Slice 切片、Map 映射`有序与无序输出演示。
|
|||
|
|
|||
|
```go
|
|||
|
func demo5() {
|
|||
|
// Array
|
|||
|
var Arr = [...]int{1, 2, 6, 4, 5}
|
|||
|
// Slice
|
|||
|
var Sli = []int{1, 2, 6, 4, 5}
|
|||
|
// Map
|
|||
|
var Map = map[string]int{
|
|||
|
"a1": 1,
|
|||
|
"b2": 2,
|
|||
|
"c3": 3,
|
|||
|
"d6": 6,
|
|||
|
"e5": 5,
|
|||
|
}
|
|||
|
|
|||
|
fmt.Printf("Type : %T, Value : %v \n", Arr, Arr)
|
|||
|
for _, A := range Arr {
|
|||
|
fmt.Printf("%v ", A)
|
|||
|
}
|
|||
|
fmt.Println()
|
|||
|
fmt.Printf("Type : %T, Value : %v \n", Sli, Sli)
|
|||
|
for _, S := range Sli {
|
|||
|
fmt.Printf("%v ", S)
|
|||
|
}
|
|||
|
fmt.Println()
|
|||
|
fmt.Printf("Type : %T, Value : %v \n", Map, Map)
|
|||
|
for _, M := range Map {
|
|||
|
fmt.Printf("%v ", M)
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
执行结果:
|
|||
|
|
|||
|
```go
|
|||
|
Type : [5]int, Value : [1 2 6 4 5]
|
|||
|
1 2 6 4 5
|
|||
|
Type : []int, Value : [1 2 6 4 5]
|
|||
|
1 2 6 4 5
|
|||
|
Type : map[string]int, Value : map[a1:1 b2:2 c3:3 d6:6 e5:5]
|
|||
|
1 2 3 6 5
|
|||
|
```
|