笔者接触 golang 也有两年的时间了,最常用的以string为key map 类型无非就是 map[string] 基础类型(int、string、float等)、map[string]interface{}、map[string]struct 这几类,说来惭愧,以前抽象数据结构,在用多维 map 的时候都是将第二维的 map 用一个单独的 struct 包装之后再使用。
以前都是这么用的:
//key 代表姓名
//value 代表年龄
type person struct {
ageInfo map[string]int
}
//key 代表班级
//value 代表该班级的学生
class := map[string][]person
了解新玩法了之后,感觉打开了一扇大门:
//第一维 map 的 key 表示班级
//第二维 map 代表学生,key 为姓名, value 为年龄
class := map[string]map[string]int
多维 map 用法
按照上面的例子,抽象结构之后,很可能会这么写代码
package main
import (
"fmt"
)
func main() {
cm := make(map[string]map[string]int,0)
cm["三年一班"]["王小明"] = 10
fmt.Println("info", cm)
}
你以为这么写真的对吗?运行一下看看结果:
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
/tmp/sandbox913968657/main.go:9 +0xa0
果然不能这么轻易就成功,报错提示正在给一个 nil map 赋值,可是 cm 这个不是已经初始化了吗?别忘了,编译器可不知道 cm 这个 map 是二维的 map ,所以在使用的时候就需要你手动的赋值了
正确给二维 map 赋值的姿势
笨笨的姿势
最容易想到的,往往就是那个最繁琐的姿势,所以以后写代码的时候要多想想
package main
import (
"fmt"
)
func main() {
cm := make(map[string]map[string]int,0)
pm := make(map[string]int,0)
pm["王小明"] = 10
cm["三年一班"] = pm
fmt.Println("info", cm)
}
运行结果:
info map[三年一班:map[王小明:10]]
更优美的姿势
作为一名追求完美软件开发人员,下面这种应该是你最合适的选择:
package main
import (
"fmt"
)
func main() {
cm := make(map[string]map[string]int,0)
cm["三年一班"] = map[string]int{
"王小明": 10,
}
fmt.Println("info", cm)
}
运行结果:
info map[三年一班:map[王小明:10]]
很多时候,写代码之前多想想就会有很多的新收获,你以为文章到这里就结束了?no,下面我要分享我的新收获了。
多问问为什么?
golang 中的引用类型有 map、channel、slice(int、string、float等其它的类型为值类型)引用类型就是在访问过程中修改存储的值,这种修改在后续的操作中是可见的。那么问题来了:
- map 的 value 用什么类型比较合适?
- 二维 map 见过了之后,考虑下 map 的 value 如果是 slice 类型这种应该怎么赋值?
map 的 value 用值还是引用
其实正确答案我也不知道,但个人认为这个跟你自己的要存储的数据有关,如果修改需要对后续的操作可见,就用引用类型;如果对占用的内存有限制,也用引用类型
注意: 暂时只想到这两个,后续持续补充好了��
map 的 value 是 slice 类型
秉承举一反三的思维,我猜你肯定也是这么写的:
package main
import (
"fmt"
)
func main() {
cm := make(map[string][]string,0)
cm["三年一班"] = []string{"王小明","李晓红"}
fmt.Println("first print info", cm)
//增加一个元素试试
cm["三年一班"] = append(cm["三年一班"],"夏天")
fmt.Println("second print info", cm)
}
打印结果:
first print info map[三年一班:[王小明 李晓红]]
second print info map[三年一班:[王小明 李晓红 夏天]]