九、Go语言快速入门之map

文章目录

    • Map
      • [:one: 使用`Map`](#:one: 使用Map)
        • [:star2: 声明和初始化](#:star2: 声明和初始化)
        • [:star2: `map`容量](#:star2: map容量)
        • [:star2: 用切片作为`map`的值](#:star2: 用切片作为map的值)
      • [:two: 测试键值对是否存在及删除元素](#:two: 测试键值对是否存在及删除元素)
      • [:three: `For`-`range`](#:three: For-range)
      • [:four: `map`类型的切片](#:four: map类型的切片)
      • [:five: map的排序](#:five: map的排序)
      • :six:将map的健和值对调

📦 使用版本为1.21.5

Map

在很多编程语言中都有map的存在,在Python中叫做字典,在java中也叫map,它的存储形式是key-value

1️⃣ 使用Map

🌟 声明和初始化

⭐️ map是引用类型,可以使用如下方法来声明一个map,注意只是声明一个map,而不是初始化

可以使用make来分配内存,不要使用new如果你错误的使用 new() 分配了一个引用对象,你会获得一个空引用的指针,相当于声明了一个未初始化的变量并且取了它的地址

go 复制代码
func main() {
	var map1 map[string]int     //声明一个map,基础方法 其中string为key的类型,int为value的类型
	map2 := make(map[string]int) //使用make这里是初始化map了
    map3 := map[string]int{"one":1,"two":2}
}
  • 在声明的时候不需要知道map的长度,它也是动态增长的
  • 未初始化的map的值是nil
  • key可以是任意能使用==或者!=操作符比较的类型(string,int,float),数组和切片、结构体不可以作为key,但是接口和指针类型可以(后面会学),如果需要用结构体来作为key,可以使用Key()Hash()方法通过计算结构体的域来计算出唯一的数字或者字符串的key(后面会学)
  • value可以是任意类型的,可以使用空接口类(后面会学),可以存储任意值,但是使用这种类型作为值时需要先做一次类型断言(后面会学)

map 传递给函数的代价很小:在 32 位机器上占 4 个字节,64 位机器上占 8 个字节,无论实际上存储了

多少数据。通过 key 在 map 中寻找值是很快的,比线性查找快得多,但是仍然比从数组和切片的索引中

直接读取要慢 100 倍;所以如果你很在乎性能的话还是建议用切片来解决问题

⭐️ map可以用函数作为value,这里就可以用来做分支结构,直接调用value对应的key来调用此函数

go 复制代码
func main() {
	map1 := map[string]func() int{
		"one": func() int {
			return 1
		},
		"two": func() int {
			return 2
		},
		"three": func() int {
			return 3
		},
	}
	fmt.Println(map1) //输出的是地址
}

map[one:0xe33c60 three:0xe33ca0 two:0xe33c80]


//或者是
func main() {
	map1 := map[string]func(i int) int{
		"one": func(i int) int {
			return i
		},
		"two": func(i int) int {
			return i
		},
		"three": func(i int) int {
			return i
		},
	}
	fmt.Println(map1["one"](4)) //输出4
}

⭐️ 调用value的方法和数组类似,直接就是map名[key名]就好了,

go 复制代码
func main() {
	map1 := map[string]int{"one": 1, "two": 2} //声明一个map,基础方法 其中string为key的类型,int为value的类型
	map1["three"] = 3                          //将map1的可以three的值改为3,如果没有这个key则添加
	
	test := map1["two"] //将指定key的赋予给test,如果key类型不存在则会被赋值为map1类型的空值
	fmt.Print(map1["one"], map1["two"], map1["three"], test)
}

//输出
1 2 3 2

⭐️ 如果想要删除键值对,直接使用delete即可

go 复制代码
	map1 := map[string]int{"one": 1, "four": 4, "five": 5, "three": 3, "two": 2}
	delete(map1, "four")
🌟 map容量

⭐️ map可以根据新增的key-value来动态的伸缩,因此它不存在固定长度或者最大限制,但是在初始化的时候可以选择表面map的初始容量

go 复制代码
func main() {
	map1 := make(map[string]int,100) //在切片中使用make是一样的
}

map 增长到容量上限的时候,如果再增加新的key-value对,map 的大小会自动加 1。所以出于性能

的考虑,对于大的 map 或者会快速扩张的 map,即使只是大概知道容量,也最好先标明

🌟 用切片作为map的值

⭐️ 既然一个 key 只能对应一个 value,而 value 又是一个原始类型,那么如果一个 key 要对应多个值怎么

办?例如,当我们要处理unix机器上的所有进程,以父进程(pid 为整形)作为 key,所有的子进程(以

所有子进程的 pid 组成的切片)作为 value。通过将 value 定义为 []int 类型或者其他类型的切片,就可

以优雅的解决这个问题

go 复制代码
func main() {
	map1 := make(map[int][]int)
}

2️⃣ 测试键值对是否存在及删除元素

⭐️ 在获取一个键值对时,就算哪个键不存在,也会返回一个value所属类型的空值,不好判断这个key是否存在,可以使用下面这种方法来判断是否存在

test 返回一个 bool 值:如果 two 存在于 map1two 就是 two 对应的 value 值,并且
testtrue;如果 two 不存在,va 就是一个空值,并且 test 会返回 false

go 复制代码
func main() {
	var va int
	var test bool
	map1 := make(map[string]int)
	map1["one"] = 1
	int, test = map1["tow"] 
	println(test, va)
}

3️⃣ For-range

⭐️ 和数组切片一样,但是map 不是按照 key 的顺序排列的,也不是按照 value 的序排列的

go 复制代码
func main() {
	map1 := make(map[string]int)
	map1["one"] = 1
	map1["two"] = 2
	map1["three"] = 3
	for key, value := range map1 {
		println("Key: ", key, "Value: ", value)
	}
}

//第一次输出
Key:  one Value:  1
Key:  two Value:  2
Key:  three Value:  3
//第二次输出
Key:  three Value:  3
Key:  one Value:  1
Key:  two Value:  2

4️⃣ map类型的切片

⭐️ 想获取一个 map 类型的切片,我们必须使用两次 make() 函数,第一次分配切片,第二次分配

切片中每个 map 元素

go 复制代码
func main() {
	map1 := make([]map[string]int, 5) //分配切片
	for i := range map1 {
		map1[i] = make(map[string]int, 1) //分配切片中的每个map元素
		map1[i]["a"] = i
	}
	fmt.Print(map1)
}

⚠️ 错误方法

go 复制代码
func main() {
	map1 := make([]map[string]int, 5)
	for _, test := range map1 {
		test = make(map[string]int, 1) //这里只是获取map的一个拷贝,并不是修改map
		test["a"] = 2
	}
	fmt.Print(map1) 
}
//输出
[map[] map[] map[] map[] map[]]

5️⃣ map的排序

⭐️ map是无序的,如果你想为 map 排序,需要将 key(或者 value)拷贝到一个切片,再对切片排序(使用 sort 包,然后可以使用切片的 for-range 方法打印出所有的 keyvalue

go 复制代码
func main() {
	map1 := map[string]int{"one": 1, "four": 4, "five": 5, "three": 3, "two": 2}
	delete(map1, "four")
	test := make([]string, len(map1)) //创建一个切片,长度为map1的长度
	var i int                         //i为切片的索引
	for key, _ := range map1 {        //读取map的key值,存入对应索引的test切片
		test[i] = key
		i++
	}
	sort.Strings(test)         //使用sort排序切片
	for _, key := range test { //去读按照切片内的值
		fmt.Printf("Key:%v,Value: %v ", key, map1[key])
	}
}

//输出:
Key:five,Value: 5 Key:one,Value: 1 Key:three,Value: 3 Key:two,Value: 2

6️⃣将map的健和值对调

⭐️ 很难直接对map使用键和值对调,因为可能是键和值的类型不一样,

go 复制代码
func main() {
	map1 := map[string]int{"one": 1, "four": 4, "five": 5, "three": 3, "two": 2} //初始map
	map2 := make(map[int]string, len(map1)) //键值对调后的map
	for k, v := range map1 {
		map2[v] = k
	}
	fmt.Println(map2)
}
相关推荐
码点1 分钟前
【无标题】日文字库Japan.ini
开发语言
IT=>小脑虎5 分钟前
2026版 Python零基础小白学习知识点【基础版详解】
开发语言·python·学习
2501_940414088 分钟前
搞了一次平台工程,我把本地的 Docker Desktop 彻底卸了
运维·docker·容器
wjs202415 分钟前
抽象工厂模式
开发语言
lly20240616 分钟前
SVG 模糊效果详解
开发语言
期待のcode18 分钟前
Java虚拟机类加载机制
java·开发语言
看见繁华25 分钟前
Linux 交叉编译实践笔记
linux·运维·笔记
Learner25 分钟前
Python运算符
开发语言·python
一晌小贪欢29 分钟前
Python 精确计算:告别浮点数陷阱,decimal 模块实战指南
开发语言·python·python入门·python3·python小数·python浮点数
咕噜企业分发小米30 分钟前
直播云服务器安全防护有哪些最新的技术趋势?
运维·服务器·安全