map
map关键字用来定义字典,其语法格式是:
map[key]value
从形式上看,有点怪异,中括号里边是字段的key值,value是key对应的值,通过key来查询value值,key与value之间形成关联关系。在字典中key值不能重复,value可以重复。
定义一个字典类型变量语法格式如下:
var 变量名 map[dataType]dataType
var 变量名 map[dataType]dataType = make(map[dataType]dataType)
var 变量名 = make(map[dataType]dataType)
var 变量名 map[dataType]dataType = map[dataType]dataType{}
var 变量名 = map[dataType]dataType{}
变量名 := map[dataType]dataType{}
变量名 := make(map[dataType]dataType)
下边来一段例子创建并初始化字典:
package main
import (
"fmt"
)
func main() {
// 定义字典类型变量的7种方法
var rel map[string]string
// 定义字典类型变量,并初始化
var rela map[string]string = map[string]string{}
// 定义字典类型变量,并初始化
var relaa = map[string]string{}
// 定义字典类型变量,并初始化
var relb map[string]string = make(map[string]string)
// 定义字典类型变量,并初始化
var relbb = make(map[string]string)
// 定义字典类型变量,并初始化
relc := make(map[string]string)
// 定义字典类型变量,并初始化
relcc := map[string]string{}
fmt.Println(rel, rela, relaa, relb, relbb, relc, relcc)
}
字典赋值
在给字典变量赋值之前,一定要初始化字典,初始化字典变量有两种方法,第一种是使用make关键字,第二种是使用map[dataType]dataType{}形式初始化:
var rel = make(map[string]string)
var relb = map[string]string{}
只有初始化完成之后,才能对字典类型变量进行赋值操作。
var rel map[string]string
rel = make(map[string]string)
// 中括号内的字符串 "a" 是key值, 赋值符号右边的 "1" 是key对应的value
rel["a"] = "1"
在給字典类型变量赋值或者查询值时,一定要初始化字典变量,否则会提示下边错误信息:
panic: assignment to entry in nil map
读取字典
读取字典,就是根据key值,在字典中查找key对应的value值,读取字典通常有两种方法,分别是:
// 第一种情况,断言查询
val,ok := map[key]
// 第二种情况直接查询
val := map[key]
上边两种读取字典的方法中,第一种采用断言的方式,当ok为true时,表示key存在于字典中,当ok为false时,表示key不存在于字典中。第二种情况直接查询key值的方式,如果key不在map种时,返回值是字典定义中value的类型默认初始值。如value的类型为int,则默认值为0,如果value类型是指针,则默认是nil,下边请看一段示例:
package main
import (
"fmt"
)
func main() {
// 定义字典,并初始化字典
rel := map[string]int{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
}
// 断言查询
val, ok := rel["a"]
fmt.Println("key 值是否存在:", ok, "key 对应的value是:", val)
// 直接查询
d := rel["b"]
fmt.Println("key 对应的value是:", d)
//断言查询不存在的key
nval, yes := rel["abcd"]
fmt.Println("key 值是否存在:", yes, "key 对应的value是:", nval)
// 直接查询不存在的key
nd := rel["abcd"]
fmt.Println("key 对应的value是:", nd)
}
输出信息是:
key 值是否存在: true key 对应的value是: 1
key 对应的value是: 2
key 值是否存在: false key 对应的value是: 0
key 对应的value是: 0
从输出信息可以看出,当key值不在字典中时,返回的是key值对应value类型的初始值,在定义字典类型变量rel时,设定value的类型是int型,int初始值是0,当访问的key值为”abcd”时,由于”abcd”不存在于字典rel中,所以返回了int的默认值0。
并发不安全
golang的map在并发情况下访问是不安全的,也就是各个goroutine之间同时使用一个map类型变量时,如果有goroutine修改了map变量值,其他goroutine可能读取到脏数据的情况,如果要保持数据一致性,需要借助于读写锁。
在golang 1.9之后,sdk在sync包中提供了一个实现并发模式下安全的抽象类型,即sync.Map, 这个不是golang语法中的关键字,只是一个实现了并发安全的实现字典管理功能的结构体。sync.Map功能将会在标准库分析章节中进行介绍。在这里,需要记住一点,map类型变量是在并发下使用是不安全的,需要借助读写锁才能实现并发安全。