字典的定义
字典是由若干个 key:value
键值对映射组合在一起的数据结构。
字典是基于哈希表的实现,每个映射里的 key
都是唯一且必须是可哈希的,即 key
是不可变类型。
字典的 key
和 value
都有各自的数据类型,在声明字典时必须指定 key
和 value
是什么类型的,然后使用 map
关键字创建字典。
字典的声明初始化
字典的声明和初始化一般分为四种方式。
第一种,声明并初始化:
var data map[string]string = map[string]string{
"id": "1",
"name": "极客点儿",
}
第二种,简化声明并初始化:
data := map[string]string{
"id": "1",
"name": "极客点儿",
}
第三种,使用 make()
先声明后赋值:
data := make(map[string]string)
data["id"] = "1"
data["name"] = "极客点儿"
第四种,先声明,然后使用 make()
申请内存空间,最后赋值:
var data map[string]string
data = make(map[string]string)
data["id"] = "1"
data["name"] = "极客点儿"
先声明 data
是一个 map
类型,此时未初始化的 data
的零值是 nil
,无法直接进行赋值,需要使用 make()
申请内存空间,最后再赋值。
正常情况下,不会有人使用第四种这种繁琐的声明方式,最常用的是第二、第三种。
字典的类型
字典的声明和数组、切片有一点不同的是字典需要同时给 key
和 value
声明类型。
那么如果我想把不同的类型混合在字典里,比如:字典中的 value
有可能是 int
和 string
类型同时存在。这种情况该如何实现呢?
其实 Go
语言为了提升字典的灵活性,提供了一种任意类型的类型 interface{}
:
data := make(map[string]interface {})
data["id"] = 1
data["name"] = "极客点儿"
这样 value
就可以是任意类型了。
当然也可以将 key
也声明为可哈希范围内的任意类型:
data := make(map[interface {}]string)
data[1] = "1"
data["name"] = "极客点儿"
key
和 value
都声明为任意类型:
data := make(map[interface {}]interface {})
data[1] = 1
data["name"] = "极客点儿"
在实际开发中,第一种是最常用的,即 key
声明为字符串,value
声明为任意类型。
字典的操作
字典的操作比较简单,最常见的是增删改查操作。
新增:
data["user"] = "Golang"
修改:
data["name"] = "Golang"
若 key
已存在则直接更新对应的 value
。
删除:
delete(data, "user")
使用 delete()
删除字典中的元素,当 key
不存在时,delete()
直接忽略不会报错。
查看:
通过下标的方式访问:
fmt.Println(data)
fmt.Println(data["id"])
fmt.Println(data["name"])
fmt.Println(data["user"])
当 key
不存在时,访问字典并不会报错,而是会返回其 value
数据类型的默认空值。
通过 for-range
进行迭代,迭代还可以分为三种方式。
获取 key
和 value
:
for key, value := range data {
fmt.Println(key, value)
}
只获取 key
,可以使用占位符 _
忽略返回值:
for key, _ := range data {
fmt.Println(key)
}
也可以不使用占用符:
for key := range data {
fmt.Println(key)
}
只获取 value
,占位符 _
是必须要的,用来忽略返回值:
for _, value := range data {
fmt.Println(value)
}
判断 key 是否存在
因为字典的特性,当 key
不存在时,访问字典并不会报错,而是会返回其 value
数据类型的默认空值。但是有可能 key
的值恰好就是空值,所以不能直接使用空值来判断 key
是否存在。
其实读取字典的数据是有两个值的,通常我们只需要第一个值,即字典本身的数据。第二个值则是对应的 key
是否存在的布尔值,若存在则为 true
否则就是 false
。
_, status := data["name"]
fmt.Println(status) // true
_, status = data["user"]
fmt.Println(status) // false