1- 13 - Map 集合
1+ 13 - Map
22========================
33
44上一节:[ 第十二篇 变参函数] ( /docs/golang_tutorial_12.md )
88
99## 什么是 map?
1010
11- Map 是 Go 中的内置类型,它将键与值绑定到一起。可以通过键获取相应的值。
11+ Map 是 Go 中的内置类型,它将键与值绑定到一起。可以通过键获取相应的值。Map与其他语言(例如Python)中的dictionary非常相似。
1212
13- ## 如何创建 map?
13+ ## 如何创建 map?
1414
1515可以通过将键和值的类型传递给内置函数 ` make ` 来创建一个 ` map ` 。语法为:` make(map[KeyType]ValueType) ` 。(译者注:` map ` 的类型表示为 ` map[KeyType]ValueType ` )例如:
1616
1717``` golang
1818personSalary := make (map [string ]int )
1919```
2020
21- 上面的代码创建了一个名为 ` personSalary ` 的 map。其中键的类型为 string,值的类型为 int。
21+ 上面的代码创建了一个名为 ` personSalary ` 的 map。其中键的类型为 ` string ` ,值的类型为 ` int ` 。
2222
23- ** map 的 0 值为 ` nil ` 。试图给一个 nil map 添加元素给会导致运行时错误。因此 map 必须通过 make 来初始化** (译者注:也可以使用速记声明来创建 map,见下文)。
23+ ** map 的 0 值为 ` nil ` 。试图给一个 nil map 添加元素给会导致运行时错误。因此 map 必须通过 ` make ` 来初始化** (译者注:也可以使用速记声明来创建 map,见下文)。
2424
2525``` golang
2626package main
@@ -42,7 +42,8 @@ func main() {
4242
4343## 向 map 中插入元素
4444
45- 插入元素给 map 的语法与数组相似。下面的代码插入一些新的元素给 ` map personSalary ` 。
45+ 插入元素给 map 的语法与数组相似。下面的代码插入一些新的元素给名为 ` personSalary ` 的 map。
46+ 4647``` golang
4748package main
4849
@@ -61,7 +62,7 @@ func main() {
6162
6263上面的程序输出:` personSalary map contents: map[steve:12000 jamie:15000 mike:9000] ` 。
6364
64- 也可以在声明时初始化一个数组 :
65+ 也可以在声明时初始化一个 map :
6566
6667``` golang
6768package main
@@ -86,7 +87,7 @@ func main() {
8687personSalary map contents: map [steve:12000 jamie:15000 mike:9000 ]
8788```
8889
89- ` string ` 并不是可以作为键的唯一类型,其他所有可以比较的类型,比如,布尔类型,整型,浮点型,复数类型都可以作为键。如果你想了解更多关于可比较类型的话,请参阅:http://golang.org/ref/spec#Comparison_operators
90+ ` string ` 并不是可以作为键的唯一类型,其他所有可以比较的类型,比如,布尔类型,整型,浮点型,复数类型都可以作为键。甚至用户自定义的类型,如 ` struct ` ,也可以作为键。 如果你想了解更多关于可比较类型的话,请参阅:http://golang.org/ref/spec#Comparison_operators
9091
9192## 访问 map 中的元素
9293
@@ -140,7 +141,7 @@ Salary of jamie is 15000
140141Salary of joe is 0
141142```
142143
143- 上面的程序返回 ` joe ` 的工资为` 0 ` 。我们没有得到任何运行时错误说明键 joe 在 ` personSalary ` 中不存在。
144+ 上面的程序返回 ` joe ` 的工资为` 0 ` 。我们没有得到任何运行时错误说明键 ` joe ` 在 ` personSalary ` 中不存在。
144145
145146我们如何检测一个键是否存在于一个 map 中呢?可以使用下面的语法:
146147
@@ -180,7 +181,9 @@ func main() {
180181joe not found
181182```
182183
183- range for 可用于遍历 map 中所有的元素(译者注:这里 range 操作符会返回 map 的键和值)。
184+ ## 遍历 map 中的所有元素
185+ 186+ ` for ` 循环的 ` range ` 形式可用于遍历 map 中所有的元素(译者注:这里 ` range ` 操作符会返回 map 的键和值)。
184187
185188``` golang
186189package main
@@ -193,8 +196,8 @@ func main() {
193196 personSalary := map [string ]int {
194197 " steve" : 12000 ,
195198 " jamie" : 15000 ,
199+ " mike" : 9000 ,
196200 }
197- personSalary[" mike" ] = 9000
198201 fmt.Println (" All items of a map" )
199202 for key , value := range personSalary {
200203 fmt.Printf (" personSalary[%s ] = %d \n " , key, value)
@@ -211,11 +214,11 @@ personSalary[steve] = 12000
211214personSalary[jamie] = 15000
212215```
213216
214- 值得注意的是,因为 map 是无序的,因此对于程序的每次执行,不能保证使用 range for 遍历 map 的顺序总是一致的。
217+ 值得注意的是,因为 map 是无序的,因此对于程序的每次执行,不能保证使用 ` for range ` 遍历 map 的顺序总是一致的,而且遍历的顺序也不完全与元素添加的顺序一致。
215218
216219## 删除元素
217220
218- ` delete(map, key) ` 用于删除 map 中的 key。 delete 函数没有返回值。
221+ ` delete(map, key) ` 用于删除 map 中的键。 ` delete ` 函数没有返回值。
219222
220223``` golang
221224package main
@@ -244,6 +247,62 @@ map before deletion map[steve:12000 jamie:15000 mike:9000]
244247map after deletion map [mike:9000 jamie:15000 ]
245248```
246249
250+ 如果我们试图删除一个原 map 中不存在的键,运行 ` delete ` 时仍不会报错。
251+ 252+ ## 结构体 map (Map of Structs)
253+ 254+ 目前我们编写了存储员工工资的 map,那么可否将员工的国籍也存储在 map 中呢?这可以通过结构体 map 来完成。每个员工可以用一个包含了"工资"和"国籍"的结构体来表示,这些结构体将被存储在一个键为 ` string ` 类型,值为 ` struct ` 类型的 map 中。
255+ 256+ ``` golang
257+ package main
258+ 259+ import (
260+ " fmt"
261+ )
262+ 263+ type employee struct {
264+ salary int
265+ country string
266+ }
267+ 268+ func main () {
269+ emp1 := employee{
270+ salary: 12000 ,
271+ country: " USA" ,
272+ }
273+ emp2 := employee{
274+ salary: 14000 ,
275+ country: " Canada" ,
276+ }
277+ emp3 := employee{
278+ salary: 13000 ,
279+ country: " India" ,
280+ }
281+ employeeInfo := map [string ]employee{
282+ " Steve" : emp1,
283+ " Jamie" : emp2,
284+ " Mike" : emp3,
285+ }
286+ 287+ for name , info := range employeeInfo {
288+ fmt.Printf (" Employee: %s Salary:$%d Country: %s \n " , name, info.salary , info.country )
289+ }
290+ 291+ }
292+ ```
293+ 294+ 以上程序中,` employee ` 结构体包含了 ` salary ` 和 ` country ` 。
295+ 296+ 在第25行,我们创建了一个 map,键为字符串类型,值为 ` employee ` 结构体,并添加了我们创建的三个员工。
297+ 298+ 在第31行,我们遍历这个 map,打印出所有员工的信息:
299+ 300+ ``` golang
301+ Employee: Mike Salary :$13000 Country : India
302+ Employee: Steve Salary :$12000 Country : USA
303+ Employee: Jamie Salary :$14000 Country : Canada
304+ ```
305+ 247306## map 的大小
248307
249308用内置函数 ` len ` 获取 map 的大小:
@@ -303,7 +362,7 @@ Person salary changed map[jamie:15000 mike:18000 steve:12000]
303362
304363## 比较 map
305364
306- map 不能通过 ` == ` 操作符比较是否相等。` == ` 操作符只能用来检测 map 是否为 nil。
365+ map 不能通过 ` == ` 操作符比较是否相等。` == ` 操作符只能用来检测 map 是否为 ` nil ` 。
307366
308367``` golang
309368package main
@@ -323,7 +382,7 @@ func main() {
323382
324383上面的程序将会报错:` invalid operation: map1 == map2 (map can only be compared to nil) ` 。
325384
326- 比较两个 map 是否相等的方式是一一比较它们的元素是否相等。我会鼓励你为此编写一个程序,使其工作:)
385+ 比较两个 map 是否相等的方式是一一比较它们的元素是否相等。希望你能自己探索并编写一个达成这一功能的程序:)
327386
328387我(原文作者)已经将我们讨论的所有概念汇总到一个程序中,你可以从 [ github] ( https://github.com/golangbot/arraysandslices ) 下载。
329388
@@ -363,6 +422,8 @@ func main(){
363422 " school" :" BAT_UN"
364423 }
365424 fmt.Println (m4)
425+ 426+ // 方式五
366427 m5 := make (map [string ][string ])
367428 m5[" name" ] = " Linux"
368429 m5[" school" ] = " Unix"
@@ -397,7 +458,7 @@ func main(){
397458 fmt.Println (m_b, ok) // OK b true
398459
399460 // 迭代操作
400- s_map := make ([]map [int ]string ,5 ) // 以 map 为元素的slice 使用 make 创建一个切片,元素的slic
461+ s_map := make ([]map [int ]string ,5 ) // 以 map 为元素的 slice 使用 make 创建一个切片,切片内的每个元素为一个 map
401462 for _,v := range s_map {
402463 v = make (map [int ]string ) // v 是值的拷贝
403464 v[1 ] = " OK"
0 commit comments