Go 编程基础 map 07

map

  • 类似其他语言中的哈希表或者字典, 以key-value形式储存数据
  • key必须是支持 == 或者 != 比较运算的类型, 不可以是函数, map或slice
  • Map查找比线性搜索快很多,但比使用索引访问数据的类型慢100倍
  • Map使用make()创建,支持 := 这种简写方式

  • make([KeyType]ValueType,cap) ,cap 表示容量, 可省略
  • 使用容量时会自动扩容, 但尽量提供一个合理的初始值
  • 使用len()获取元素个数

  • 键值对不存在是自动添加,使用delete()删除某键值对
  • 使用 for range 对 map 和 slice 进行迭代操作

创建一个map

最原始方式

var m1 map[int]string
m1 = map[int]string{}
fmt.Println(m1)
map[]

"连等"make创建

var m2 map[int]string = make(map[int]string)

最简创建

m3 := make(map[int]string)

存取删除key

func main() {
    m3 := make(map[int]string)
    fmt.Println(m3)
    m3[1] = "hello"
    fmt.Println(m3)
    fmt.Println(m3[1])
    delete(m3,1)
    fmt.Println(m3[1])
}
map[]
map[1:hello]
hello

多级Map

创建一个map下面又是一个map的数据结构

func main() {
    var m map[int]map[int]string
    m = make(map[int]map[int]string)
    m[1][1] = "OK"
    a := m[1][1]
    fmt.Println(a)
}

其实这里就会报错, 因为我们只是make了最外层的map[int],而map[int]后面的map[int]string我们并没有make

panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()

修改之后代码

这里你要对那个下标赋值..你就必须对那个下标进行 make

func main() {
    var m map[int]map[int]string
    m = make(map[int]map[int]string)
    //这里我们需要对内存的map进行make
    m[1] = make(map[int]string)
    fmt.Println(m)
    m[1][1] = "OK"
    a := m[1][1]
    fmt.Println(m)
    fmt.Println(a)
    delete(m[1],1)
    fmt.Println(m)
}
map[1:map[]]
map[1:map[1:OK]]
OK
map[1:map[]]

最粗暴的深层map的make方法

func main() {
    var m map[int]map[int]string
    m = make(map[int]map[int]string)
    //这里我们就需要用到返回值的第二个参数,如果是已经make的就会返回true,没有make的就会返回false
    a, isMake := m[2][1]
    fmt.Println(a, isMake)
    if !isMake {
        m[2] = make(map[int]string)
    }
    m[2][1] = "OK"
    a, isMake = m[2][1]
    fmt.Println(a, isMake)
}
 false
OK true

这种方法有个缺陷是... 如果是三层map,那么你需要再make,很麻烦

map for range迭代make

func main() {
    //创建一个元素类型是map的slice
    //map[int]string 是map
    sm := make([]map[int]string, 5)
    for k, v := range sm {
        //迭代make
        v = make(map[int]string, 1)
        v [1] = "OK"
        fmt.Println(k, v)
    }
    fmt.Println(sm)
}
0 map[1:OK]
1 map[1:OK]
2 map[1:OK]
3 map[1:OK]
4 map[1:OK]
[map[] map[] map[] map[] map[]]

最后打印出来的sm却是初始值,,这就说明了..我们在迭代过程中只是值拷贝

map for range迭代 真的修改值

func main() {
    //创建一个元素类型是map的slice
    //map[int]string 是map
    sm := make([]map[int]string, 5)
    //那么这里我们需要用到map的k
    for k := range sm {
        //make当前k
        sm[k] = make(map[int]string, 1)
        //赋值
        sm[k][1] = "OK"
        fmt.Println(k, sm[k])
    }
    fmt.Println(sm)
}
0 map[1:OK]
1 map[1:OK]
2 map[1:OK]
3 map[1:OK]
4 map[1:OK]
[map[1:OK] map[1:OK] map[1:OK] map[1:OK] map[1:OK]]

作业

map键值替换

func main() {
    m1 := map[int]string{7: "a", 2: "b", 3: "c"}
    m2 := make(map[string]int)
    for k, v := range m1 {
        m2[v] = k
    }
    fmt.Println(m1)
    fmt.Println(m2)
}
map[7:a 2:b 3:c]
map[c:3 a:7 b:2]

注意这里的m2的数据类型一定不要定义错 我最开始定义成了m2 := make(map[int]string) 就出现以下错误

# command-line-arguments
./basic_structure.go:32:5: cannot use v (type string) as type int in map index
./basic_structure.go:32:9: cannot use k (type int) as type string in assignment