GO语言中的复合类型除了数组、切片之外,还有一个map;说起map估计大家都不陌生,因为在Java、C++等语言中有它的身影,它以<key,value>的形式为程序员提供服务。

【Go语言】【10】GO语言的map_GO

从图中也可以看出:内存中存储了六个城市信息,其中key是城市电话区号,value是城市名称。对于城市电话区号(key)是唯一的,这样方便程序员对城市名称(value)进行增、删、改、查等操作;另外<key,value>之间也存在一定的关联,即图中的箭头,但这种关联关系对GO语言的初学者来说并不需要特别关心。


一、map声明、初始化和赋值

1、声明格式:var 变量名 map[key值类型]value值类型

例如:

var cityMap map[string]string

var employeeMap map[int]string

var boolMap map[string]bool


2、map初始化

var cityMap map[string]string = map[string]string{"010": "北京", "022": "天津", "021": "上海", "020": "广州", "0755": "深圳", "0571": "杭州"}

var employeeMap map[int]string = map[int]string{1: "Boss", 2: "manager", 3: "employee"}

var boolMap map[string]bool = map[string]bool{"朝鲜": true, "日本": false, "伊朗": true, "中国": true, "俄罗斯": false}


当然,若嫌这句太长,可以简化如下:

var cityMap = map[string]string{"010": "北京", "022": "天津", "021": "上海", "020": "广州", "0755": "深圳", "0571": "杭州"}

var employeeMap = map[int]string{1: "Boss", 2: "manager", 3: "employee"}

var boolMap = map[string]bool{"朝鲜": true, "日本": false, "伊朗": true, "中国": true, "俄罗斯": false}


还可以这样简化:

cityMap := map[string]string{"010": "北京", "022": "天津", "021": "上海", "020": "广州", "0755": "深圳", "0571": "杭州"}

employeeMap := map[int]string{1: "Boss", 2: "manager", 3: "employee"}

boolMap := map[string]bool{"朝鲜": true, "日本": false, "伊朗": true, "中国": true, "俄罗斯": false}


若上面两种简化方式还是感觉太长,可以采用赋值方式

3、map赋值

var cityMap map[string]string   // 声明cityMap变量

var employeeMap map[int]string  // 声明employeeMap变量

var boolMap map[string]bool    // 声明boolMap变量


cityMap = map[string]string{}   // 初始化变量cityMap

cityMap["010"] = "北京"       // 对变量cityMap进行赋值

cityMap["022"] = "天津"

cityMap["021"] = "上海"

cityMap["020"] = "广州"

cityMap["0755"] = "深圳"

cityMap["0571"] = "杭州"


employeeMap = map[int]string{} // 初始化变量employeeMap

employeeMap[1] = "Boss"      // 对变量employeeMap进行赋值

employeeMap[2] = "manager"

employeeMap[3] = "employee"


boolMap = map[string]bool{}    // 初始化变量boolMap

boolMap["朝鲜"] = true       // 对变量boolMap进行赋值

boolMap["日本"] = false

boolMap["伊朗"] = true

boolMap["中国"] = true

boolMap["俄罗斯"] = false


二、创建和遍历map

1、使用make创建map

除了上面的方式声明map之外,还可以类似slice采用GO语言内置函数make()来创建一个新map。上例可以改写如下:

cityMap := make(map[string]string)

employeeMap := make(map[int]string)

boolMap := make(map[string]bool)


map的创建与slice的创建类似,也可以在创建时指定map的容量

cityMap := make(map[string]string, 6)

employeeMap := make(map[int]string, 3)

boolMap := make(map[string]bool, 5)


2、遍历map

下面通过一个示例来了解如何遍历map:(1)创建map并赋值(2)遍历map(3)删除电话区号为022的城市

// 创建map并赋值

cityMap := make(map[string]string, 6)

cityMap["010"] = "北京"

cityMap["022"] = "天津"

cityMap["021"] = "上海"

cityMap["020"] = "广州"

cityMap["0755"] = "深圳"

cityMap["0571"] = "杭州"

fmt.Println(cityMap)


// 遍历map

for k, _ := range cityMap {

    // 删除电话区号为022的城市

    if k == "022" {

        delete(cityMap, k)

    }

}

fmt.Println(cityMap)

程序运行结果为:

【Go语言】【10】GO语言的map_map_02


3、多返回值

    GO语言与Java、C++等一个极大不同之处在于:多返回值,GO语言的函数可以有多个返回值,这个特性使得代码编写更简洁

for key, value := range cityMap{

   // 略

}

这里使用遍历cityMap时,就把该map之间的<key,value>值都返回了,程序员即可以使用key值,也可以使用value,假设程序员不需要value值,则可以像上例一样,把value更改为_

for key, _  := range cityMap{

   // 略

}


三、map注意事项

1、map以<key, value>的形式存储数据,其中key必须是支持==或者!=运算的类型,而不能是map、slice或者函数

2、map查找比线性搜索速度快

3、判断map元素个数使用len()函数,而不是size()

4、GO语言使用内置delete()函数删除map中的元素,第一个参数是map,第二个参数是map中的key,若这个key不存在,则什么都不发生,但若key被设置为nil,那么这个删除将会抛出异常


四、map中的value

map中的value类型可以是基础类型,也可以是复合类型,也可以是结构体


1、value类型为结构体

【value类型为结构体的存储模型示意图】:

【Go语言】【10】GO语言的map_map_03


【程序实现】:

// 定义结构体

type Persion struct {

    Name, Phone string

    Age         int

}

// 创建map,它的value类型为Persion

persionMap := make(map[string]Persion)

// 给map中元素赋值,其key类型为字符串,value类型为Persion

persionMap["123456"] = Persion{Name: "纠正哥", Age: 35, Phone: "13581887557"}

persionMap["789012"] = Persion{Name: "裸跑弟", Age: 5, Phone: "none"}

// 遍历map打印出Persion信息

for _, value := range persionMap {

    fmt.Println("姓名:", value.Name, "\t年龄:", value.Age, "\t电话:", value.Phone)

}

【运行结果】:

【Go语言】【10】GO语言的map_GO_04


2、value类型为map

【程序实现】:

// 创建map,它的value类型为map

persionMap := make(map[string]map[string]string)


persionMap["123456"] = map[string]string{"name": "纠正哥", "phone": "13581887557", "age": "35"}

persionMap["789012"] = map[string]string{"name": "裸跑弟", "phone": "none", "age": "5"}


// 遍历map打印出Persion信息

for _, value := range persionMap {

    fmt.Println("姓名:", value["name"], "\t年龄:", value["age"], "\t电话:", value["phone"])

}

【运行结果】:

【Go语言】【10】GO语言的map_GO_04

【说明】:

当vlaue类型为map时,与上例value类型为结构体Persion相似,只不过健值对处的value是一个map,但若非找出不相同之处,那就是map以泛型的形式出现,像本例中尽管age的值是整型,但由于泛型的要求,这里的年龄必须使用双引号括起来。