字典定义

go中支持字典类型的数据,所谓字典类型,指的是一个键值对的关系集合。一个键对应一个值,go中的字典是一个无序集合,不会根据键或值进行排序。
在go中声明字典:

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. func main() {
  7. var map1 map[string]int
  8. fmt.Println(map1)
  9. map2 := map[string]int{
  10. "one": 1,
  11. "two": 2,
  12. }
  13. fmt.Println(map2)
  14. key := "two"
  15. value, ok := map2[key]
  16. if ok {
  17. fmt.Printf("map has key:" + key + " values is:" + strconv.Itoa(value))
  18. } else {
  19. fmt.Printf("map no has key")
  20. }
  21. }

字典声明

var map1 map[string]int

在go中声明字典需要指定键的数据类型以及值得数据类型

字典初始化

我们可以通过先声明再初始化的方式进行初始化,就像上面示例代码做的那样,也可以通过 := 将声明和初始化合并为一条语句:

map2 := map[string]int{
        "one": 1,
        "two": 2,
}

还可以通过make函数来初始化一个字典,使用make函数创建的字典可以直接赋值。直接声明不允许这样操作,因为数据没被初始化为nil赋值会直接抛异常。

package main

func main() {
    map1 := make(map[string]int)
    map1["test"] = 1
    map1["test2"] = 2
}

也可以选择是否在创建时指定该字典的初始存储能力(超出会自动扩容):

testMap = make(map[string]int, 100)

元素赋值

直接指定key和值便可以对字典进行修改

map1["test"] = 1

字段初始化之后才能进行赋值操作,如果仅仅是声明,此时 testMap 的值为 nil,在 nil 上进行操作编译期间会报 panic(运行时恐慌),导致编译不通过。

查找元素

上面的示例代码已经显示,在字典中输入键值,可以返回两个参数,一个为键的值,第二个参数为布尔类型代表是否获取成功,如果失败第一个参数为nil。

  value, ok := map2[key]
    if ok {
        fmt.Printf("map has key:" + key + " values is:" + strconv.Itoa(value))
    } else {
        fmt.Printf("map no has key")
    }

:::warning 需要注意的是,go的字典内部是通过hash表来实现的。当用户设置键值时,首先会将键转换为一个hash值进行存储。而在查找时也会将键转换为hash值在hash表中进行查询,从而提交查找性能。但是hash会存在hash冲突,即不同的键也会产生同样的hash值,这个时候 Go 底层还会判断原始键的值和类型是否相等。也正因如此,我们在声明字典的键类型时,要求数据类型必须是支持通过 == 或 != 进行判等操作的类型,比如数字类型、字符串类型、数组类型、结构体类型等,不过为了提高字典查询性能,类型长度越短约好,通常,我们会将其设置为整型或者长度较短的字符串类型。 :::

删除元素

Go 语言提供了一个内置函数 delete(),用于删除容器内的元素,我们可以通过这个函数来实现字典元素的删除:

package main

import "fmt"

func main() {
    map1 := make(map[string]int)
    map1["test"] = 1
    map1["test2"] = 2
    fmt.Println(map1)
    delete(map1, "test")
    fmt.Println(map1)
}

:::warning 这个键不存在或者字典尚未初始化,这个调用也不会有什么副作用。 :::