1.1.1. 一、map 的基本介绍。

map 是 key-value 数据结构,又称为字段或者关联数组。**类似其它编程语言的集合**, 在编程中是经常使用到。

1.1.2. 二、map 的声明语法。

1、语法如下:

var map 变量名 map[keytype]valuetype

// 示例: var students map[string]string
  • keytype 是键的类型:可以是 bool、 数字、string、指针、channel、 还可以是只包含前面几个类型的接口、 结构体、数组。通常 key 为 int 、string。注意:slice, map 还有 function 不可以,因为这几个没法用 == 来判断。
  • valuetype 是值的类型:可以的类型 和 keytype 基本一样。通常为: 数字(整数、浮点数)、string、map、struct。
  • 如果key重复了,后面设置的值会覆盖前面的值。

2、map 声明的举例。

  • var a map[string]string 键类型是string,值类型是string。
  • var a map[string]int 键类型是string,值类型是int。
  • var a map[string]map[string]string 键类型是string,值类型是map[string]string ,另一个map。

注意:声明是不会分配内存的,make 分配内存后才能赋值和使用。

3、给map分配内存。

  • 先声明,然后用make分配空间。
    var students map[string]string

    // 使用map前,需要先给map分配空间
    students = make(map[string]string,10)

    students["s1"] = "张三"
    students["s2"] = "李四"
    fmt.Println(students) // map[s1:张三 s2:李四]
  • 声明时使用make分配空间。不写空间大小。
    // 声明时直接make分配空间,不写空间大小
    var students = make(map[string]string)

    students["s1"] = "张三"
    students["s2"] = "李四"
    fmt.Println(students) // map[s1:张三 s2:李四]
  • 声明的时候直接初始化。
    students := map[string]string{
        "s1" : "张三",
        "s2" : "李四",
    }
    students["s3"] = "王5"

    fmt.Println(students) // map[s1:张三 s2:李四 s3:王5]

4、示例嵌套map的使用。

    var students = make(map[string]map[string]string)

    //第一个学生
    students["001"] = make(map[string]string)

    //设置students["001"]是一个map。这里设置这个map的“name”
    students["001"]["name"] = "张三"
    students["001"]["sex"] = "男"
    students["001"]["age"] = "18"

    // map[001:map[age:18 name:张三 sex:男]]
    fmt.Println(students)

1.1.3. 三、map的CRUD(增删改查)操作。

1、增加、修改操作。

map["key"] = value //如果 key 还没有,就是增加,如果 key 存在就是修改。

2、删除 map 的元素:

delete(map,"key") // 删除map 中键为"key"的元素

delete 是一个内置函数,如果 key 存在,就删除该 key-value,如果 key 不存在, 不操作,但是也不会报错。

    var students = make(map[string]string)
    students["name"] = "张三"
    students["age"] = "18"
    // map[age:18 name:张三]
    fmt.Println(students)

    delete(students,"name") //删除key是"name"的元素

    delete(students,"sss") //删除不存在的key,不报错。
    fmt.Println(students) //map[age:18]

如果我们要删除 map 的所有 key ,没有一个专门的方法一次删除,可以遍历一下 key,逐个删除或者 map = make(...),make 一个新的,让原来的成为垃圾,被 gc 回收。

3、查找map的元素。

value,flag := students["name"]

说明:查找返回两个值。第一个是根据key找到的值,第二个是bool型表示是否找到。

  • 如果找到了,flag等于true。
  • 如果找不到 value 会返回值类型的零值,flag等于false。
  • 也可以使用students["name"] != nil判断存在这个key。

示例如下:

    var students = make(map[string]string)
    students["name"] = "张三"
    students["age"] = "18"

    // map的查找
    value,flag := students["name"]

    if flag {
        // 查找到了value=张三,flag=true
        fmt.Printf("查找到了value=%v,flag=%v",value,flag)
    }else {
        // 如果找不到 value 会返回值类型的零值,flag=false
        fmt.Printf("不存在value=%v,flag=%v",value,flag)
    }

1.1.4. 四、map的遍历。

map不能用普通for循环变量,只能使用for-range遍历。示例如下:

    var students = make(map[string]string)
    students["name"] = "张三"
    students["age"] = "18"

    //遍历,k就是键的值。v就是值。
    for k,v := range students {
        fmt.Printf("键是 %v,值是 %v \n",k,v)
    }

1.1.5. 五、map的长度。

使用len()函数。可以得到map的长度,也就是有多少个键值对。

    var students = make(map[string]string)
    students["name"] = "张三"
    students["age"] = "18"
    fmt.Println(len(students)) // 2

1.1.6. 六、map的切片。

切片的数据类型如果是 map,则我们称为 slice of map,map切片,这样使用则 map 的个数就可以动态变化了。

实际上就是一个数组,里面的每一个元素都是一个map。

var students = make([]map[string]string)

完整示例如下:

    // 声明 map[string]string 类型的切片,并且数组大小是2
    var students = make([]map[string]string,2)
    //设置第一个元素
    if students[0] == nil {
        students[0] = make(map[string]string)
        students[0]["name"] = "张三"
        students[0]["age"] = "18"
    }
    if students[1] == nil {
        students[1] = make(map[string]string)
        students[1]["name"] = "张三"
        students[1]["age"] = "18"
    }

    // 没有students[2],这里会报错:数组越界。因为上面只声明了2个空间。如果需要加元素,使用append。

    // [map[age:18 name:张三] map[age:18 name:张三]]
    fmt.Println(students)


    stu := map[string]string{
        "name":"王5",
    }
    // 给切片增加一个元素。
    students = append(students, stu)

    // [map[age:18 name:张三] map[age:18 name:张三] map[name:王5]]
    fmt.Println(students)

注意几点:

  • var students = make([]map[string]string,2) 这个表示切片的初始大小是2。对map[string]string类型切片。
  • 其实就是声明了一个数组,里面的每一个元素都是一个map。
  • 不能使用 students[2] ,使用了会报错:数组越界。因为上面只声明了2个空间。如果需要加元素,使用append。
  • students = append(students, stu) 给切片(动态数组)增加了一个元素。

1.1.7. 七、对map的key排序。

map是无序的,如果想按照key对map排序输出。实现代码如下:

    // 声明 map
    var studentsMp = make(map[int]int,6)
    studentsMp[6] = 10
    studentsMp[81] = 9
    studentsMp[34] = 67
    studentsMp[8] = 4

    // int 类型切片
    var keys []int
    for k,_ := range studentsMp{
        keys = append(keys,k)
    }
    // 把keys递增排序
    sort.Ints(keys)
    for _,k := range keys{
        fmt.Println(k,studentsMp[k]) //按照key获取studentsMp的值
    }

整体思路是把key放在一个切片里。然后对key的切片排序,使用的是sort包的sort.Ints()方法。

1.1.8. 八、map的使用陷阱。

  1. map 是引用类型,遵守引用类型传递的机制,在一个函数接收 map,修改后,会直接修改外部原来的 map 。
  2. map 的容量达到后,再想 map 增加元素,会自动扩容,并不会发生 panic,也就是说 map 能动态的增长 键值对(key-value)。

results matching ""

    No results matching ""