1. 前言

Map的数据结构是key-value,可通过key来快速检索数据,类似其它语言中的字典、hash等,由于Map是使用hash表实现的,所以它也是无序的,不能决定它返回的顺序。

2. Map定义

map 是引用类型的,使用时需要先声明

var mapname map[keytype]valuetype

map 未初始化值是 nil, 可使用make()来初始化

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

map可根据新增的键值对来动态的伸缩容量,无最大限制,cap是非必须的参数,但是我们在初始化时一般会给它指定一个合适的容量。

示例:

package main

import "fmt"

func main() {
    price := make(map[string]int, 8)
    price["apple"] = 8
    price["grape"] = 18
    fmt.Println(price)

    // 也可声明时直接赋值
    fruits := map[string]string{
        "apple": "苹果",
        "grape": "葡萄",
    }
    fmt.Println(fruits)
    fmt.Println(fruits["grape"],":",price["grape"])
}

输出:

map[apple:8 grape:18]
map[apple:苹果 grape:葡萄]
葡萄 : 18

3. 判断键值对是否存在

在上述代码里,我们直接Println出fruits["grape"],要是grape键值对不存在的话fruits["grape"]就会返回空值,这样子我们就不能区分它是不存在还是对应的值就是空。

为了解决这个问题,go中有个判断map中键是否存在的特殊写法,格式如下:

 value, ok := map[key]

ok 为bool类型,key存在ok为true;不存在ok为false,value为空值

示例:

package main

import "fmt"

func main() {
    // 也可声明时直接赋值
    fruits := map[string]string{
        "apple": "苹果",
        "grape": "葡萄",
    }

    v, ok := fruits["apple"]
    if ok {
        fmt.Println(v)
    }

    _, ok = fruits["apple123"]

    if !ok {
        fmt.Println("apple123不存在")
    }

}

输出:

苹果
apple123不存在

4. 键值对删除

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

delete(map, key)

key不在map时,delete操作不会产生错误。

示例:

package main

import "fmt"

func main() {
    // 也可声明时直接赋值
    fruits := map[string]string{
        "apple": "苹果",
        "grape": "葡萄",
    }

    fmt.Println("原始:", fruits)

    // 将apple:苹果从fruits中删除
    delete(fruits, "apple")

    fmt.Println("删除后:", fruits)

    // 删除不存在的键值对,不会报错
    delete(fruits, "apple123")
}

输出:

原始: map[apple:苹果 grape:葡萄]
删除后: map[grape:葡萄]

5. map遍历

和数组切片一样,map也可以使用循环

示例:

package main

import (
    "fmt"
)

func main() {

    var grade = make(map[string]int, 5)

    for i := 0; i < 5; i++ {
        key := fmt.Sprintf("map-%02d", i)
        grade[key] = i
    }

    //取出map中的所有key存入切片keys
    for key, value := range grade {
        fmt.Printf("%v : %d\n", key, value)
    }
}

输出:

map-02 : 2
map-03 : 3
map-04 : 4
map-00 : 0
map-01 : 1

6. map排序

可以看到上面 map遍历输出的结果是乱序的,这也证实了map是无序的,那要想map有序输出,也是有办法的,借助切片对map的键值去排序后循环输出即可,代码如下:

package main

import (
    "fmt"
    "sort"
)

func main() {

    var grade = make(map[string]int, 5)

    for i := 0; i < 5; i++ {
        key := fmt.Sprintf("map-%02d", i)
        grade[key] = i
    }

    // 取出grade中的所有key
    var keys = make([]string, 0, len(grade))
    for key := range grade {
        keys = append(keys, key)
    }

    // 对切片keys进行排序
    sort.Strings(keys)

    // 按照排序后的key遍历grade
    for _, key := range keys {
        fmt.Println(key, grade[key])
    }
}

输出:

map-00 0
map-01 1
map-02 2
map-03 3
map-04 4

7. map类型的切片

获取一个map 类型的切片,需要使用两次make(),第一次初始化切片,第二次初始化切片中每个map元素

示例:

package main

import (
    "fmt"
)

func main() {
    fmt.Println("对切片进行初始化")
    var fruits = make([]map[string]string, 3)
    for key, value := range fruits {
        fmt.Printf("key:%d value:%v\n", key, value)
    }
    fmt.Println("对切片中的map元素进行初始化")
    fruits[0] = make(map[string]string, 10)
    fruits[0]["apple"] = "苹果"
    fruits[0]["grape"] = "葡萄"
    fruits[0]["banana"] = "香蕉"
    for key, value := range fruits {
        fmt.Printf("key:%d value:%v\n", key, value)
    }
}

输出:

对切片进行初始化
key:0 value:map[]
key:1 value:map[]
key:2 value:map[]
对切片中的map元素进行初始化
key:0 value:map[apple:苹果 banana:香蕉 grape:葡萄]
key:1 value:map[]
key:2 value:map[]

8. 切片类型的map

package main

import (
"fmt"
)

func main() {
    fmt.Println("对map进行初始化")
    var fruits = make(map[string][]string, 3)
    fmt.Println(fruits)

    fmt.Println("对切片进行初始化")
    slice := make([]string, 0, 3)
    fruits["常见水果"] = append(slice, "苹果", "葡萄", "香蕉")
    fmt.Println(fruits)
}

输出:

对map进行初始化
map[]
对切片进行初始化
map[常见水果:[苹果 葡萄 香蕉]]
Copyright © yzx该文章修订时间: 2021-10-12 15:54:45

results matching ""

    No results matching ""