Golang中存储键值对的数据类型是映射,即map,由于映射这个中文词汇比较生硬,又没有其他更好的中文词,因此后面还是直接用英文map。
什么是map
Golang中map是一种用来存储键值对的数据类型,可以通过键(key) 来设置 或读取 对应的值(value) 。
创建map
可以使用make
函数来创建一个map,语法如下:
Copy make(map[key_type]value_type)
例如我们可以创建一个名为personSalary
的map来存储大家的薪水:
Copy personSalary := make(map[string]int)
该map的key类型为string
,value类型为int
。
map数据类型对应的零值 为nil
。如果尝试向值为nil
的map中添加元素会报错。因此一般情况下需要通过make
函数来初始化一个空map。
Copy package main
import "fmt"
func main() {
var personSalary map[string]int
if personSalary == nil {
fmt.Println("map is nil. Going to make one.")
personSalary = make(map[string]int)
}
}
Copy map is nil. Going to make one.
添加元素
向map内添加元素的语法跟数组添加元素一致。下面的程序向map personSalary
内添加了几项元素:
Copy package main
import "fmt"
func main() {
personSalary := make(map[string]int)
personSalary["steve"] = 12000
personSalary["jamie"] = 15000
personSalary["mike"] = 9000
fmt.Println("personSalary map contents:", personSalary)
}
Copy personSalary map contents: map[jamie:15000 mike:9000 steve:12000]
map也可以在声明时同时进行初始化。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
fmt.Println("personSalary map contents:", personSalary)
}
访问元素
我们已经了解如何向map中添加元素了,现在我们看下如何访问map元素。访问map元素的语法为map[key]
。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
employee := "jamie"
fmt.Println("Salary of", employee, "is", personSalary[employee])
}
Copy Salary of jamie is 15000
如果我们访问的某个key在map中不存在,map会返回value类型对应的零值。比如对于personSalary
,如果我们访问的元素不存在,则会返回int
类型对应的零值0
。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
fmt.Println("Salary of joe is", personSalary["joe"])
}
虽然mappersonSalary
中并没有元素joe
,但是该程序执行并没有报错,personSalary["joe"]
返回了值0
。
那如果我们就是想知道map中是否含有某个key
怎么办呢?Golang提供了如下方式:
Copy value, ok := map[key]
如果ok
为true
,表示map中含有该key
,否则不含有。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
newEmp := "joe"
salary, ok := personSalary[newEmp]
if ok == true {
fmt.Println("Salary of", newEmp, "is", salary)
} else {
fmt.Println(newEmp, "not found")
}
}
类似数组和切片,我们可以使用for range
来迭代访问map。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
for key, value := range personSalary {
fmt.Printf("personSalary[%s] = %d\n", key, value)
}
}
Copy personSalary[steve] = 12000
personSalary[jamie] = 15000
使用for range
迭代访问map有一点需要注意,每次迭代访问map元素的访问次序不保证 。
删除元素
从map中删除元素的语法为delete(map, key)
。这里delete
函数调用时无返回值。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
fmt.Println("map before deletion", personSalary)
delete(personSalary, "steve")
fmt.Println("map after deletion", personSalary)
}
Copy map before deletion map[jamie:15000 steve:12000]
map after deletion map[jamie:15000]
获取map中元素个数
len
函数可以获取map中元素的个数。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
fmt.Println("length is", len(personSalary))
}
map是引用类型
Golang中,map和切片(slice)相同,都是引用类型。如果我们把一个map变量赋值给另外一个变量,这两个变量指向同一个底层存储空间,任何一个变量对内部元素进行了修改都会反映到另一个变量上。
Copy package main
import "fmt"
func main() {
personSalary := map[string]int {
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
fmt.Println("Original person salary", personSalary)
newPersonSalary := personSalary
newPersonSalary["mike"] = 18000
fmt.Println("Person salary changed", personSalary)
}
Copy Original person salary map[jamie:15000 mike:9000 steve:12000]
Person salary changed map[jamie:15000 mike:18000 steve:12000]
这点在函数传参的时候也会同样试用,需要注意。
判断相等
两个map不能通过==
运算符进行比较,==
仅可以用来跟nil
值进行比较。
Copy package main
func mian() {
map1 := map[string]int {
"one": 1,
"two": 2,
}
map2 := map1
if map1 == map2 {
}
}
Copy invalid operation: map1 == map2 (map can only be compared to nil)
如果我们确实像判断两个map是否相等,可以遍历两个map来判断每个键值对是否相同,以间接判断。