2015-12-09 07:57:17 +00:00
<!DOCTYPE HTML>
< html lang = "zh-tw" >
< head >
< meta charset = "UTF-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" / >
2015-12-31 08:20:27 +00:00
< title > Map | Go语言圣经< / title >
2015-12-09 07:57:17 +00:00
< meta content = "text/html; charset=utf-8" http-equiv = "Content-Type" >
< meta name = "description" content = "" >
< meta name = "generator" content = "GitBook 2.5.2" >
< meta name = "HandheldFriendly" content = "true" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1, user-scalable=no" >
< meta name = "apple-mobile-web-app-capable" content = "yes" >
< meta name = "apple-mobile-web-app-status-bar-style" content = "black" >
< link rel = "apple-touch-icon-precomposed" sizes = "152x152" href = "../gitbook/images/apple-touch-icon-precomposed-152.png" >
< link rel = "shortcut icon" href = "../gitbook/images/favicon.ico" type = "image/x-icon" >
< link rel = "stylesheet" href = "../gitbook/style.css" >
2015-12-28 08:08:26 +00:00
< link rel = "stylesheet" href = "../gitbook/plugins/gitbook-plugin-katex/katex.min.css" >
2015-12-09 07:57:17 +00:00
< link rel = "stylesheet" href = "../gitbook/plugins/gitbook-plugin-highlight/website.css" >
< link rel = "stylesheet" href = "../gitbook/plugins/gitbook-plugin-fontsettings/website.css" >
< link rel = "next" href = "../ch4/ch4-04.html" / >
< link rel = "prev" href = "../ch4/ch4-02.html" / >
< / head >
< body >
2015-12-31 08:20:27 +00:00
< div class = "book" data-level = "4.3" data-chapter-title = "Map" data-filepath = "ch4/ch4-03.md" data-basepath = ".." data-revision = "Thu Dec 31 2015 16:18:40 GMT+0800 (中国标准时间)" >
2015-12-09 07:57:17 +00:00
< div class = "book-summary" >
< nav role = "navigation" >
< ul class = "summary" >
< li class = "chapter " data-level = "0" data-path = "index.html" >
< a href = "../index.html" >
< i class = "fa fa-check" > < / i >
前言
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "0.1" data-path = "ch0/ch0-01.html" >
< a href = "../ch0/ch0-01.html" >
< i class = "fa fa-check" > < / i >
< b > 0.1.< / b >
Go語言起源
< / a >
< / li >
< li class = "chapter " data-level = "0.2" data-path = "ch0/ch0-02.html" >
< a href = "../ch0/ch0-02.html" >
< i class = "fa fa-check" > < / i >
< b > 0.2.< / b >
Go語言項目
< / a >
< / li >
< li class = "chapter " data-level = "0.3" data-path = "ch0/ch0-03.html" >
< a href = "../ch0/ch0-03.html" >
< i class = "fa fa-check" > < / i >
< b > 0.3.< / b >
本書的組織
< / a >
< / li >
< li class = "chapter " data-level = "0.4" data-path = "ch0/ch0-04.html" >
< a href = "../ch0/ch0-04.html" >
< i class = "fa fa-check" > < / i >
< b > 0.4.< / b >
更多的信息
< / a >
< / li >
< li class = "chapter " data-level = "0.5" data-path = "ch0/ch0-05.html" >
< a href = "../ch0/ch0-05.html" >
< i class = "fa fa-check" > < / i >
< b > 0.5.< / b >
2015-12-21 04:55:18 +00:00
致謝
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "1" data-path = "ch1/ch1.html" >
< a href = "../ch1/ch1.html" >
< i class = "fa fa-check" > < / i >
< b > 1.< / b >
入門
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "1.1" data-path = "ch1/ch1-01.html" >
< a href = "../ch1/ch1-01.html" >
< i class = "fa fa-check" > < / i >
< b > 1.1.< / b >
Hello, World
< / a >
< / li >
< li class = "chapter " data-level = "1.2" data-path = "ch1/ch1-02.html" >
< a href = "../ch1/ch1-02.html" >
< i class = "fa fa-check" > < / i >
< b > 1.2.< / b >
命令行參數
< / a >
< / li >
< li class = "chapter " data-level = "1.3" data-path = "ch1/ch1-03.html" >
< a href = "../ch1/ch1-03.html" >
< i class = "fa fa-check" > < / i >
< b > 1.3.< / b >
2015-12-21 04:55:18 +00:00
査找重複的行
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "1.4" data-path = "ch1/ch1-04.html" >
< a href = "../ch1/ch1-04.html" >
< i class = "fa fa-check" > < / i >
< b > 1.4.< / b >
2015-12-21 04:55:18 +00:00
GIF動畵
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "1.5" data-path = "ch1/ch1-05.html" >
< a href = "../ch1/ch1-05.html" >
< i class = "fa fa-check" > < / i >
< b > 1.5.< / b >
2015-12-28 08:08:26 +00:00
獲取URL
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "1.6" data-path = "ch1/ch1-06.html" >
< a href = "../ch1/ch1-06.html" >
< i class = "fa fa-check" > < / i >
< b > 1.6.< / b >
2015-12-28 08:08:26 +00:00
併發獲取多個URL
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "1.7" data-path = "ch1/ch1-07.html" >
< a href = "../ch1/ch1-07.html" >
< i class = "fa fa-check" > < / i >
< b > 1.7.< / b >
Web服務
< / a >
< / li >
< li class = "chapter " data-level = "1.8" data-path = "ch1/ch1-08.html" >
< a href = "../ch1/ch1-08.html" >
< i class = "fa fa-check" > < / i >
< b > 1.8.< / b >
本章要點
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "2" data-path = "ch2/ch2.html" >
< a href = "../ch2/ch2.html" >
< i class = "fa fa-check" > < / i >
< b > 2.< / b >
程序結構
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "2.1" data-path = "ch2/ch2-01.html" >
< a href = "../ch2/ch2-01.html" >
< i class = "fa fa-check" > < / i >
< b > 2.1.< / b >
命名
< / a >
< / li >
< li class = "chapter " data-level = "2.2" data-path = "ch2/ch2-02.html" >
< a href = "../ch2/ch2-02.html" >
< i class = "fa fa-check" > < / i >
< b > 2.2.< / b >
聲明
< / a >
< / li >
< li class = "chapter " data-level = "2.3" data-path = "ch2/ch2-03.html" >
< a href = "../ch2/ch2-03.html" >
< i class = "fa fa-check" > < / i >
< b > 2.3.< / b >
變量
< / a >
< / li >
< li class = "chapter " data-level = "2.4" data-path = "ch2/ch2-04.html" >
< a href = "../ch2/ch2-04.html" >
< i class = "fa fa-check" > < / i >
< b > 2.4.< / b >
賦值
< / a >
< / li >
< li class = "chapter " data-level = "2.5" data-path = "ch2/ch2-05.html" >
< a href = "../ch2/ch2-05.html" >
< i class = "fa fa-check" > < / i >
< b > 2.5.< / b >
類型
< / a >
< / li >
< li class = "chapter " data-level = "2.6" data-path = "ch2/ch2-06.html" >
< a href = "../ch2/ch2-06.html" >
< i class = "fa fa-check" > < / i >
< b > 2.6.< / b >
包和文件
< / a >
< / li >
< li class = "chapter " data-level = "2.7" data-path = "ch2/ch2-07.html" >
< a href = "../ch2/ch2-07.html" >
< i class = "fa fa-check" > < / i >
< b > 2.7.< / b >
作用域
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "3" data-path = "ch3/ch3.html" >
< a href = "../ch3/ch3.html" >
< i class = "fa fa-check" > < / i >
< b > 3.< / b >
基礎數據類型
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "3.1" data-path = "ch3/ch3-01.html" >
< a href = "../ch3/ch3-01.html" >
< i class = "fa fa-check" > < / i >
< b > 3.1.< / b >
整型
< / a >
< / li >
< li class = "chapter " data-level = "3.2" data-path = "ch3/ch3-02.html" >
< a href = "../ch3/ch3-02.html" >
< i class = "fa fa-check" > < / i >
< b > 3.2.< / b >
浮點數
< / a >
< / li >
< li class = "chapter " data-level = "3.3" data-path = "ch3/ch3-03.html" >
< a href = "../ch3/ch3-03.html" >
< i class = "fa fa-check" > < / i >
< b > 3.3.< / b >
2015-12-21 04:55:18 +00:00
複數
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "3.4" data-path = "ch3/ch3-04.html" >
< a href = "../ch3/ch3-04.html" >
< i class = "fa fa-check" > < / i >
< b > 3.4.< / b >
2015-12-21 04:55:18 +00:00
布爾型
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "3.5" data-path = "ch3/ch3-05.html" >
< a href = "../ch3/ch3-05.html" >
< i class = "fa fa-check" > < / i >
< b > 3.5.< / b >
字符串
< / a >
< / li >
< li class = "chapter " data-level = "3.6" data-path = "ch3/ch3-06.html" >
< a href = "../ch3/ch3-06.html" >
< i class = "fa fa-check" > < / i >
< b > 3.6.< / b >
常量
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "4" data-path = "ch4/ch4.html" >
< a href = "../ch4/ch4.html" >
< i class = "fa fa-check" > < / i >
< b > 4.< / b >
2015-12-21 04:55:18 +00:00
複合數據類型
2015-12-09 07:57:17 +00:00
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "4.1" data-path = "ch4/ch4-01.html" >
< a href = "../ch4/ch4-01.html" >
< i class = "fa fa-check" > < / i >
< b > 4.1.< / b >
數組
< / a >
< / li >
< li class = "chapter " data-level = "4.2" data-path = "ch4/ch4-02.html" >
< a href = "../ch4/ch4-02.html" >
< i class = "fa fa-check" > < / i >
< b > 4.2.< / b >
2015-12-31 08:20:27 +00:00
Slice
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter active" data-level = "4.3" data-path = "ch4/ch4-03.html" >
< a href = "../ch4/ch4-03.html" >
< i class = "fa fa-check" > < / i >
< b > 4.3.< / b >
2015-12-31 08:20:27 +00:00
Map
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "4.4" data-path = "ch4/ch4-04.html" >
< a href = "../ch4/ch4-04.html" >
< i class = "fa fa-check" > < / i >
< b > 4.4.< / b >
結構體
< / a >
< / li >
< li class = "chapter " data-level = "4.5" data-path = "ch4/ch4-05.html" >
< a href = "../ch4/ch4-05.html" >
< i class = "fa fa-check" > < / i >
< b > 4.5.< / b >
JSON
< / a >
< / li >
< li class = "chapter " data-level = "4.6" data-path = "ch4/ch4-06.html" >
< a href = "../ch4/ch4-06.html" >
< i class = "fa fa-check" > < / i >
< b > 4.6.< / b >
文本和HTML模闆
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "5" data-path = "ch5/ch5.html" >
< a href = "../ch5/ch5.html" >
< i class = "fa fa-check" > < / i >
< b > 5.< / b >
函數
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "5.1" data-path = "ch5/ch5-01.html" >
< a href = "../ch5/ch5-01.html" >
< i class = "fa fa-check" > < / i >
< b > 5.1.< / b >
函數聲明
< / a >
< / li >
< li class = "chapter " data-level = "5.2" data-path = "ch5/ch5-02.html" >
< a href = "../ch5/ch5-02.html" >
< i class = "fa fa-check" > < / i >
< b > 5.2.< / b >
遞歸
< / a >
< / li >
< li class = "chapter " data-level = "5.3" data-path = "ch5/ch5-03.html" >
< a href = "../ch5/ch5-03.html" >
< i class = "fa fa-check" > < / i >
< b > 5.3.< / b >
多返迴值
< / a >
< / li >
< li class = "chapter " data-level = "5.4" data-path = "ch5/ch5-04.html" >
< a href = "../ch5/ch5-04.html" >
< i class = "fa fa-check" > < / i >
< b > 5.4.< / b >
錯誤
< / a >
< / li >
< li class = "chapter " data-level = "5.5" data-path = "ch5/ch5-05.html" >
< a href = "../ch5/ch5-05.html" >
< i class = "fa fa-check" > < / i >
< b > 5.5.< / b >
函數值
< / a >
< / li >
< li class = "chapter " data-level = "5.6" data-path = "ch5/ch5-06.html" >
< a href = "../ch5/ch5-06.html" >
< i class = "fa fa-check" > < / i >
< b > 5.6.< / b >
匿名函數
< / a >
< / li >
< li class = "chapter " data-level = "5.7" data-path = "ch5/ch5-07.html" >
< a href = "../ch5/ch5-07.html" >
< i class = "fa fa-check" > < / i >
< b > 5.7.< / b >
可變參數
< / a >
< / li >
< li class = "chapter " data-level = "5.8" data-path = "ch5/ch5-08.html" >
< a href = "../ch5/ch5-08.html" >
< i class = "fa fa-check" > < / i >
< b > 5.8.< / b >
Deferred函數
< / a >
< / li >
< li class = "chapter " data-level = "5.9" data-path = "ch5/ch5-09.html" >
< a href = "../ch5/ch5-09.html" >
< i class = "fa fa-check" > < / i >
< b > 5.9.< / b >
Panic異常
< / a >
< / li >
< li class = "chapter " data-level = "5.10" data-path = "ch5/ch5-10.html" >
< a href = "../ch5/ch5-10.html" >
< i class = "fa fa-check" > < / i >
< b > 5.10.< / b >
2015-12-28 08:08:26 +00:00
Recover捕獲異常
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "6" data-path = "ch6/ch6.html" >
< a href = "../ch6/ch6.html" >
< i class = "fa fa-check" > < / i >
< b > 6.< / b >
方法
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "6.1" data-path = "ch6/ch6-01.html" >
< a href = "../ch6/ch6-01.html" >
< i class = "fa fa-check" > < / i >
< b > 6.1.< / b >
方法聲明
< / a >
< / li >
< li class = "chapter " data-level = "6.2" data-path = "ch6/ch6-02.html" >
< a href = "../ch6/ch6-02.html" >
< i class = "fa fa-check" > < / i >
< b > 6.2.< / b >
2015-12-21 04:55:18 +00:00
基於指針對象的方法
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "6.3" data-path = "ch6/ch6-03.html" >
< a href = "../ch6/ch6-03.html" >
< i class = "fa fa-check" > < / i >
< b > 6.3.< / b >
通過嵌入結構體來擴展類型
< / a >
< / li >
< li class = "chapter " data-level = "6.4" data-path = "ch6/ch6-04.html" >
< a href = "../ch6/ch6-04.html" >
< i class = "fa fa-check" > < / i >
< b > 6.4.< / b >
2015-12-21 04:55:18 +00:00
方法值和方法表達式
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "6.5" data-path = "ch6/ch6-05.html" >
< a href = "../ch6/ch6-05.html" >
< i class = "fa fa-check" > < / i >
< b > 6.5.< / b >
示例: Bit數組
< / a >
< / li >
< li class = "chapter " data-level = "6.6" data-path = "ch6/ch6-06.html" >
< a href = "../ch6/ch6-06.html" >
< i class = "fa fa-check" > < / i >
< b > 6.6.< / b >
封裝
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "7" data-path = "ch7/ch7.html" >
< a href = "../ch7/ch7.html" >
< i class = "fa fa-check" > < / i >
< b > 7.< / b >
接口
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "7.1" data-path = "ch7/ch7-01.html" >
< a href = "../ch7/ch7-01.html" >
< i class = "fa fa-check" > < / i >
< b > 7.1.< / b >
2015-12-21 04:55:18 +00:00
接口是合約
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "7.2" data-path = "ch7/ch7-02.html" >
< a href = "../ch7/ch7-02.html" >
< i class = "fa fa-check" > < / i >
< b > 7.2.< / b >
接口類型
< / a >
< / li >
< li class = "chapter " data-level = "7.3" data-path = "ch7/ch7-03.html" >
< a href = "../ch7/ch7-03.html" >
< i class = "fa fa-check" > < / i >
< b > 7.3.< / b >
實現接口的條件
< / a >
< / li >
< li class = "chapter " data-level = "7.4" data-path = "ch7/ch7-04.html" >
< a href = "../ch7/ch7-04.html" >
< i class = "fa fa-check" > < / i >
< b > 7.4.< / b >
flag.Value接口
< / a >
< / li >
< li class = "chapter " data-level = "7.5" data-path = "ch7/ch7-05.html" >
< a href = "../ch7/ch7-05.html" >
< i class = "fa fa-check" > < / i >
< b > 7.5.< / b >
接口值
< / a >
< / li >
< li class = "chapter " data-level = "7.6" data-path = "ch7/ch7-06.html" >
< a href = "../ch7/ch7-06.html" >
< i class = "fa fa-check" > < / i >
< b > 7.6.< / b >
sort.Interface接口
< / a >
< / li >
< li class = "chapter " data-level = "7.7" data-path = "ch7/ch7-07.html" >
< a href = "../ch7/ch7-07.html" >
< i class = "fa fa-check" > < / i >
< b > 7.7.< / b >
http.Handler接口
< / a >
< / li >
< li class = "chapter " data-level = "7.8" data-path = "ch7/ch7-08.html" >
< a href = "../ch7/ch7-08.html" >
< i class = "fa fa-check" > < / i >
< b > 7.8.< / b >
error接口
< / a >
< / li >
< li class = "chapter " data-level = "7.9" data-path = "ch7/ch7-09.html" >
< a href = "../ch7/ch7-09.html" >
< i class = "fa fa-check" > < / i >
< b > 7.9.< / b >
2015-12-21 04:55:18 +00:00
示例: 表達式求值
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "7.10" data-path = "ch7/ch7-10.html" >
< a href = "../ch7/ch7-10.html" >
< i class = "fa fa-check" > < / i >
< b > 7.10.< / b >
類型斷言
< / a >
< / li >
< li class = "chapter " data-level = "7.11" data-path = "ch7/ch7-11.html" >
< a href = "../ch7/ch7-11.html" >
< i class = "fa fa-check" > < / i >
< b > 7.11.< / b >
2015-12-21 04:55:18 +00:00
基於類型斷言識别錯誤類型
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "7.12" data-path = "ch7/ch7-12.html" >
< a href = "../ch7/ch7-12.html" >
< i class = "fa fa-check" > < / i >
< b > 7.12.< / b >
通過類型斷言査詢接口
< / a >
< / li >
< li class = "chapter " data-level = "7.13" data-path = "ch7/ch7-13.html" >
< a href = "../ch7/ch7-13.html" >
< i class = "fa fa-check" > < / i >
< b > 7.13.< / b >
類型分支
< / a >
< / li >
< li class = "chapter " data-level = "7.14" data-path = "ch7/ch7-14.html" >
< a href = "../ch7/ch7-14.html" >
< i class = "fa fa-check" > < / i >
< b > 7.14.< / b >
示例: 基於標記的XML解碼
< / a >
< / li >
< li class = "chapter " data-level = "7.15" data-path = "ch7/ch7-15.html" >
< a href = "../ch7/ch7-15.html" >
< i class = "fa fa-check" > < / i >
< b > 7.15.< / b >
補充幾點
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "8" data-path = "ch8/ch8.html" >
< a href = "../ch8/ch8.html" >
< i class = "fa fa-check" > < / i >
< b > 8.< / b >
Goroutines和Channels
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "8.1" data-path = "ch8/ch8-01.html" >
< a href = "../ch8/ch8-01.html" >
< i class = "fa fa-check" > < / i >
< b > 8.1.< / b >
Goroutines
< / a >
< / li >
< li class = "chapter " data-level = "8.2" data-path = "ch8/ch8-02.html" >
< a href = "../ch8/ch8-02.html" >
< i class = "fa fa-check" > < / i >
< b > 8.2.< / b >
2015-12-21 04:55:18 +00:00
示例: 併發的Clock服務
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "8.3" data-path = "ch8/ch8-03.html" >
< a href = "../ch8/ch8-03.html" >
< i class = "fa fa-check" > < / i >
< b > 8.3.< / b >
2015-12-21 04:55:18 +00:00
示例: 併發的Echo服務
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "8.4" data-path = "ch8/ch8-04.html" >
< a href = "../ch8/ch8-04.html" >
< i class = "fa fa-check" > < / i >
< b > 8.4.< / b >
Channels
< / a >
< / li >
< li class = "chapter " data-level = "8.5" data-path = "ch8/ch8-05.html" >
< a href = "../ch8/ch8-05.html" >
< i class = "fa fa-check" > < / i >
< b > 8.5.< / b >
併行的循環
< / a >
< / li >
< li class = "chapter " data-level = "8.6" data-path = "ch8/ch8-06.html" >
< a href = "../ch8/ch8-06.html" >
< i class = "fa fa-check" > < / i >
< b > 8.6.< / b >
2015-12-21 04:55:18 +00:00
示例: 併發的Web爬蟲
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "8.7" data-path = "ch8/ch8-07.html" >
< a href = "../ch8/ch8-07.html" >
< i class = "fa fa-check" > < / i >
< b > 8.7.< / b >
2015-12-21 04:55:18 +00:00
基於select的多路複用
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "8.8" data-path = "ch8/ch8-08.html" >
< a href = "../ch8/ch8-08.html" >
< i class = "fa fa-check" > < / i >
< b > 8.8.< / b >
2015-12-21 04:55:18 +00:00
示例: 併發的字典遍歷
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "8.9" data-path = "ch8/ch8-09.html" >
< a href = "../ch8/ch8-09.html" >
< i class = "fa fa-check" > < / i >
< b > 8.9.< / b >
2015-12-28 08:08:26 +00:00
併發的退出
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "8.10" data-path = "ch8/ch8-10.html" >
< a href = "../ch8/ch8-10.html" >
< i class = "fa fa-check" > < / i >
< b > 8.10.< / b >
示例: 聊天服務
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "9" data-path = "ch9/ch9.html" >
< a href = "../ch9/ch9.html" >
< i class = "fa fa-check" > < / i >
< b > 9.< / b >
2015-12-21 04:55:18 +00:00
基於共享變量的併發
2015-12-09 07:57:17 +00:00
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "9.1" data-path = "ch9/ch9-01.html" >
< a href = "../ch9/ch9-01.html" >
< i class = "fa fa-check" > < / i >
< b > 9.1.< / b >
競爭條件
< / a >
< / li >
< li class = "chapter " data-level = "9.2" data-path = "ch9/ch9-02.html" >
< a href = "../ch9/ch9-02.html" >
< i class = "fa fa-check" > < / i >
< b > 9.2.< / b >
sync.Mutex互斥鎖
< / a >
< / li >
< li class = "chapter " data-level = "9.3" data-path = "ch9/ch9-03.html" >
< a href = "../ch9/ch9-03.html" >
< i class = "fa fa-check" > < / i >
< b > 9.3.< / b >
sync.RWMutex讀寫鎖
< / a >
< / li >
< li class = "chapter " data-level = "9.4" data-path = "ch9/ch9-04.html" >
< a href = "../ch9/ch9-04.html" >
< i class = "fa fa-check" > < / i >
< b > 9.4.< / b >
2015-12-21 04:55:18 +00:00
內存同步
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "9.5" data-path = "ch9/ch9-05.html" >
< a href = "../ch9/ch9-05.html" >
< i class = "fa fa-check" > < / i >
< b > 9.5.< / b >
sync.Once初始化
< / a >
< / li >
< li class = "chapter " data-level = "9.6" data-path = "ch9/ch9-06.html" >
< a href = "../ch9/ch9-06.html" >
< i class = "fa fa-check" > < / i >
< b > 9.6.< / b >
競爭條件檢測
< / a >
< / li >
< li class = "chapter " data-level = "9.7" data-path = "ch9/ch9-07.html" >
< a href = "../ch9/ch9-07.html" >
< i class = "fa fa-check" > < / i >
< b > 9.7.< / b >
2015-12-21 04:55:18 +00:00
示例: 併發的非阻塞緩存
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "9.8" data-path = "ch9/ch9-08.html" >
< a href = "../ch9/ch9-08.html" >
< i class = "fa fa-check" > < / i >
< b > 9.8.< / b >
2015-12-21 04:55:18 +00:00
Goroutines和線程
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "10" data-path = "ch10/ch10.html" >
< a href = "../ch10/ch10.html" >
< i class = "fa fa-check" > < / i >
< b > 10.< / b >
包和工具
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "10.1" data-path = "ch10/ch10-01.html" >
< a href = "../ch10/ch10-01.html" >
< i class = "fa fa-check" > < / i >
< b > 10.1.< / b >
簡介
< / a >
< / li >
< li class = "chapter " data-level = "10.2" data-path = "ch10/ch10-02.html" >
< a href = "../ch10/ch10-02.html" >
< i class = "fa fa-check" > < / i >
< b > 10.2.< / b >
導入路徑
< / a >
< / li >
< li class = "chapter " data-level = "10.3" data-path = "ch10/ch10-03.html" >
< a href = "../ch10/ch10-03.html" >
< i class = "fa fa-check" > < / i >
< b > 10.3.< / b >
包聲明
< / a >
< / li >
< li class = "chapter " data-level = "10.4" data-path = "ch10/ch10-04.html" >
< a href = "../ch10/ch10-04.html" >
< i class = "fa fa-check" > < / i >
< b > 10.4.< / b >
導入聲明
< / a >
< / li >
< li class = "chapter " data-level = "10.5" data-path = "ch10/ch10-05.html" >
< a href = "../ch10/ch10-05.html" >
< i class = "fa fa-check" > < / i >
< b > 10.5.< / b >
匿名導入
< / a >
< / li >
< li class = "chapter " data-level = "10.6" data-path = "ch10/ch10-06.html" >
< a href = "../ch10/ch10-06.html" >
< i class = "fa fa-check" > < / i >
< b > 10.6.< / b >
包和命名
< / a >
< / li >
< li class = "chapter " data-level = "10.7" data-path = "ch10/ch10-07.html" >
< a href = "../ch10/ch10-07.html" >
< i class = "fa fa-check" > < / i >
< b > 10.7.< / b >
工具
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "11" data-path = "ch11/ch11.html" >
< a href = "../ch11/ch11.html" >
< i class = "fa fa-check" > < / i >
< b > 11.< / b >
測試
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "11.1" data-path = "ch11/ch11-01.html" >
< a href = "../ch11/ch11-01.html" >
< i class = "fa fa-check" > < / i >
< b > 11.1.< / b >
go test
< / a >
< / li >
< li class = "chapter " data-level = "11.2" data-path = "ch11/ch11-02.html" >
< a href = "../ch11/ch11-02.html" >
< i class = "fa fa-check" > < / i >
< b > 11.2.< / b >
測試函數
< / a >
< / li >
< li class = "chapter " data-level = "11.3" data-path = "ch11/ch11-03.html" >
< a href = "../ch11/ch11-03.html" >
< i class = "fa fa-check" > < / i >
< b > 11.3.< / b >
測試覆蓋率
< / a >
< / li >
< li class = "chapter " data-level = "11.4" data-path = "ch11/ch11-04.html" >
< a href = "../ch11/ch11-04.html" >
< i class = "fa fa-check" > < / i >
< b > 11.4.< / b >
基準測試
< / a >
< / li >
< li class = "chapter " data-level = "11.5" data-path = "ch11/ch11-05.html" >
< a href = "../ch11/ch11-05.html" >
< i class = "fa fa-check" > < / i >
< b > 11.5.< / b >
剖析
< / a >
< / li >
< li class = "chapter " data-level = "11.6" data-path = "ch11/ch11-06.html" >
< a href = "../ch11/ch11-06.html" >
< i class = "fa fa-check" > < / i >
< b > 11.6.< / b >
示例函數
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "12" data-path = "ch12/ch12.html" >
< a href = "../ch12/ch12.html" >
< i class = "fa fa-check" > < / i >
< b > 12.< / b >
反射
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "12.1" data-path = "ch12/ch12-01.html" >
< a href = "../ch12/ch12-01.html" >
< i class = "fa fa-check" > < / i >
< b > 12.1.< / b >
2015-12-21 04:55:18 +00:00
爲何需要反射?
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "12.2" data-path = "ch12/ch12-02.html" >
< a href = "../ch12/ch12-02.html" >
< i class = "fa fa-check" > < / i >
< b > 12.2.< / b >
reflect.Type和reflect.Value
< / a >
< / li >
< li class = "chapter " data-level = "12.3" data-path = "ch12/ch12-03.html" >
< a href = "../ch12/ch12-03.html" >
< i class = "fa fa-check" > < / i >
< b > 12.3.< / b >
Display遞歸打印
< / a >
< / li >
< li class = "chapter " data-level = "12.4" data-path = "ch12/ch12-04.html" >
< a href = "../ch12/ch12-04.html" >
< i class = "fa fa-check" > < / i >
< b > 12.4.< / b >
2015-12-21 04:55:18 +00:00
示例: 編碼S表達式
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "12.5" data-path = "ch12/ch12-05.html" >
< a href = "../ch12/ch12-05.html" >
< i class = "fa fa-check" > < / i >
< b > 12.5.< / b >
通過reflect.Value脩改值
< / a >
< / li >
< li class = "chapter " data-level = "12.6" data-path = "ch12/ch12-06.html" >
< a href = "../ch12/ch12-06.html" >
< i class = "fa fa-check" > < / i >
< b > 12.6.< / b >
2015-12-21 04:55:18 +00:00
示例: 解碼S表達式
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "12.7" data-path = "ch12/ch12-07.html" >
< a href = "../ch12/ch12-07.html" >
< i class = "fa fa-check" > < / i >
< b > 12.7.< / b >
2015-12-28 08:08:26 +00:00
獲取結構體字段標識
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "chapter " data-level = "12.8" data-path = "ch12/ch12-08.html" >
< a href = "../ch12/ch12-08.html" >
< i class = "fa fa-check" > < / i >
< b > 12.8.< / b >
顯示一個類型的方法集
< / a >
< / li >
< li class = "chapter " data-level = "12.9" data-path = "ch12/ch12-09.html" >
< a href = "../ch12/ch12-09.html" >
< i class = "fa fa-check" > < / i >
< b > 12.9.< / b >
幾點忠告
< / a >
< / li >
< / ul >
< / li >
< li class = "chapter " data-level = "13" data-path = "ch13/ch13.html" >
< a href = "../ch13/ch13.html" >
< i class = "fa fa-check" > < / i >
< b > 13.< / b >
底層編程
< / a >
< ul class = "articles" >
< li class = "chapter " data-level = "13.1" data-path = "ch13/ch13-01.html" >
< a href = "../ch13/ch13-01.html" >
< i class = "fa fa-check" > < / i >
< b > 13.1.< / b >
unsafe.Sizeof, Alignof 和 Offsetof
< / a >
< / li >
< li class = "chapter " data-level = "13.2" data-path = "ch13/ch13-02.html" >
< a href = "../ch13/ch13-02.html" >
< i class = "fa fa-check" > < / i >
< b > 13.2.< / b >
unsafe.Pointer
< / a >
< / li >
< li class = "chapter " data-level = "13.3" data-path = "ch13/ch13-03.html" >
< a href = "../ch13/ch13-03.html" >
< i class = "fa fa-check" > < / i >
< b > 13.3.< / b >
示例: 深度相等判斷
< / a >
< / li >
< li class = "chapter " data-level = "13.4" data-path = "ch13/ch13-04.html" >
< a href = "../ch13/ch13-04.html" >
< i class = "fa fa-check" > < / i >
< b > 13.4.< / b >
通過cgo調用C代碼
< / a >
< / li >
< li class = "chapter " data-level = "13.5" data-path = "ch13/ch13-05.html" >
< a href = "../ch13/ch13-05.html" >
< i class = "fa fa-check" > < / i >
< b > 13.5.< / b >
幾點忠告
< / a >
< / li >
< / ul >
< / li >
2015-12-24 06:47:06 +00:00
< li class = "chapter " data-level = "14" data-path = "CONTRIBUTORS.html" >
2015-12-09 07:57:17 +00:00
2015-12-24 06:47:06 +00:00
< a href = "../CONTRIBUTORS.html" >
2015-12-09 07:57:17 +00:00
< i class = "fa fa-check" > < / i >
2015-12-21 04:55:18 +00:00
< b > 14.< / b >
2015-12-09 07:57:17 +00:00
2015-12-24 06:47:06 +00:00
附録
2015-12-09 07:57:17 +00:00
< / a >
< / li >
< li class = "divider" > < / li >
< li >
< a href = "https://www.gitbook.com" target = "blank" class = "gitbook-link" >
本書使用 GitBook 釋出
< / a >
< / li >
< / ul >
< / nav >
< / div >
< div class = "book-body" >
< div class = "body-inner" >
< div class = "book-header" role = "navigation" >
<!-- Actions Left -->
<!-- Title -->
< h1 >
< i class = "fa fa-circle-o-notch fa-spin" > < / i >
2015-12-31 08:20:27 +00:00
< a href = "../" > Go语言圣经< / a >
2015-12-09 07:57:17 +00:00
< / h1 >
< / div >
< div class = "page-wrapper" tabindex = "-1" role = "main" >
< div class = "page-inner" >
< section class = "normal" id = "section-" >
2015-12-31 08:20:27 +00:00
< h2 id = "43-map" > 4.3. Map< / h2 >
< p > 哈 希 表 是 一 種 巧 妙 併 且 實 用 的 數 據 結 構 。 它 是 一 個 無 序 的 key/value對 的 集 合 , 其 中 所 有 的 key都 是 不 同 的 , 然 後 通 過 給 定 的 key可 以 在 常 數 時 間 複 雜 度 內 檢 索 、 更 新 或 刪 除 對 應 的 value。 < / p >
< p > 在 Go語 言 中 , 一 個 map就 是 一 個 哈 希 表 的 引 用 , map類 型 可 以 寫 爲 map[K]V, 其 中 K和 V分 别 對 應 key和 value。 map中 所 有 的 key都 有 相 同 的 類 型 , 所 以 的 value也 有 着 相 同 的 類 型 , 但 是 key和 value之 間 可 以 是 不 同 的 數 據 類 型 。 其 中 K對 應 的 key必 鬚 是 支 持 ==比 較 運 算 符 的 數 據 類 型 , 所 以 map可 以 通 過 測 試 key是 否 相 等 來 判 斷 是 否 已 經 存 在 。 雖 然 浮 點 數 類 型 也 是 支 持 相 等 運 算 符 比 較 的 , 但 是 將 浮 點 數 用 做 key類 型 則 是 一 個 壞 的 想 法 , 正 如 第 三 章 提 到 的 , 最 壞 的 情 況 是 可 能 出 現 的 NaN和 任 何 浮 點 數 都 不 相 等 。 對 於 V對 應 的 value數 據 類 型 則 沒 有 任 何 的 限 製 。 < / p >
< p > 內 置 的 make函 數 可 以 創 建 一 個 map: < / p >
< pre > < code class = "lang-Go" > ages := < span class = "hljs-built_in" > make< / span > (< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span > ) < span class = "hljs-comment" > // mapping from strings to ints< / span >
< / code > < / pre >
< p > 我 們 也 可 以 用 map字 面 值 的 語 法 創 建 map, 同 時 還 可 以 指 定 一 些 最 初 的 key/value: < / p >
< pre > < code class = "lang-Go" > ages := < span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span > {
< span class = "hljs-string" > " alice" < / span > : < span class = "hljs-number" > 31< / span > ,
< span class = "hljs-string" > " charlie" < / span > : < span class = "hljs-number" > 34< / span > ,
}
< / code > < / pre >
< p > 這 相 當 於 < / p >
< pre > < code class = "lang-Go" > ages := < span class = "hljs-built_in" > make< / span > (< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span > )
ages[< span class = "hljs-string" > " alice" < / span > ] = < span class = "hljs-number" > 31< / span >
ages[< span class = "hljs-string" > " charlie" < / span > ] = < span class = "hljs-number" > 34< / span >
< / code > < / pre >
< p > 因 此 , 另 一 種 創 建 空 的 map的 表 達 式 是 map[string]int{}。 < / p >
< p > Map中 的 元 素 通 過 key對 應 的 下 標 語 法 訪 問 : < / p >
< pre > < code class = "lang-Go" > ages[< span class = "hljs-string" > " alice" < / span > ] = < span class = "hljs-number" > 32< / span >
fmt.Println(ages[< span class = "hljs-string" > " alice" < / span > ]) < span class = "hljs-comment" > // " 32" < / span >
< / code > < / pre >
< p > 使 用 內 置 的 delete函 數 可 以 刪 除 元 素 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-built_in" > delete< / span > (ages, < span class = "hljs-string" > " alice" < / span > ) < span class = "hljs-comment" > // remove element ages[" alice" ]< / span >
< / code > < / pre >
< p > 所 有 這 些 操 作 是 安 全 的 , 卽 使 這 些 元 素 不 在 map中 也 沒 有 關 繫 ; 如 果 一 個 査 找 失 敗 將 返 迴 value類 型 對 應 的 零 值 , 例 如 , 卽 使 map中 不 存 在 “ bob” 下 面 的 代 碼 也 可 以 正 常 工 作 , 因 爲 ages[" bob" ]失 敗 時 將 返 迴 0。 < / p >
< pre > < code class = "lang-Go" > ages[< span class = "hljs-string" > " bob" < / span > ] = ages[< span class = "hljs-string" > " bob" < / span > ] + < span class = "hljs-number" > 1< / span > < span class = "hljs-comment" > // happy birthday!< / span >
< / code > < / pre >
< p > 而 且 x += y和 x++等 簡 短 賦 值 語 法 也 可 以 用 在 map上 , 所 以 上 面 的 代 碼 可 以 改 寫 成 < / p >
< pre > < code class = "lang-Go" > ages[< span class = "hljs-string" > " bob" < / span > ] += < span class = "hljs-number" > 1< / span >
< / code > < / pre >
< p > 更 簡 單 的 寫 法 < / p >
< pre > < code class = "lang-Go" > ages[< span class = "hljs-string" > " bob" < / span > ]++
< / code > < / pre >
< p > 但 是 map中 的 元 素 併 不 是 一 個 變 量 , 因 此 我 們 不 能 對 map的 元 素 進 行 取 址 操 作 : < / p >
< pre > < code class = "lang-Go" > _ = & ages[< span class = "hljs-string" > " bob" < / span > ] < span class = "hljs-comment" > // compile error: cannot take address of map element< / span >
< / code > < / pre >
< p > 禁 止 對 map元 素 取 址 的 原 因 是 map可 能 隨 着 元 素 數 量 的 增 長 而 重 新 分 配 更 大 的 內 存 空 間 , 從 而 可 能 導 致 之 前 的 地 址 無 效 。 < / p >
< p > 要 想 遍 歷 map中 全 部 的 key/value對 的 話 , 可 以 使 用 range風 格 的 for循 環 實 現 , 和 之 前 的 slice遍 歷 語 法 類 似 。 下 面 的 迭 代 語 句 將 在 每 次 迭 代 時 設 置 name和 age變 量 , 它 們 對 應 下 一 個 鍵 /值 對 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > for< / span > name, age := < span class = "hljs-keyword" > range< / span > ages {
fmt.Printf(< span class = "hljs-string" > " %s\t%d\n" < / span > , name, age)
}
< / code > < / pre >
< p > Map的 迭 代 順 序 是 不 確 定 的 , 併 且 不 同 的 哈 希 函 數 實 現 可 能 導 致 不 同 的 遍 歷 順 序 。 在 實 踐 中 , 遍 歷 的 順 序 是 隨 機 的 , 每 一 次 遍 歷 的 順 序 都 不 相 同 。 這 是 故 意 的 , 每 次 都 使 用 隨 機 的 遍 歷 順 序 可 以 強 製 要 求 程 序 不 會 依 賴 具 體 的 哈 希 函 數 實 現 。 如 果 要 按 順 序 遍 歷 key/value對 , 我 們 必 鬚 顯 式 地 對 key進 行 排 序 , 可 以 使 用 sort包 的 Strings函 數 對 字 符 串 slice進 行 排 序 。 下 面 是 常 見 的 處 理 方 式 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > import< / span > < span class = "hljs-string" > " sort" < / span >
< span class = "hljs-keyword" > var< / span > names []< span class = "hljs-typename" > string< / span >
< span class = "hljs-keyword" > for< / span > name := < span class = "hljs-keyword" > range< / span > ages {
names = < span class = "hljs-built_in" > append< / span > (names, name)
}
sort.Strings(names)
< span class = "hljs-keyword" > for< / span > _, name := < span class = "hljs-keyword" > range< / span > names {
fmt.Printf(< span class = "hljs-string" > " %s\t%d\n" < / span > , name, ages[name])
}
< / code > < / pre >
< p > 因 爲 我 們 一 開 始 就 知 道 names的 最 終 大 小 , 因 此 給 slice分 配 一 個 合 適 的 大 小 將 會 更 有 效 。 下 面 的 代 碼 創 建 了 一 個 空 的 slice, 但 是 slice的 容 量 剛 好 可 以 放 下 map中 全 部 的 key: < / p >
< pre > < code class = "lang-Go" > names := < span class = "hljs-built_in" > make< / span > ([]< span class = "hljs-typename" > string< / span > , < span class = "hljs-number" > 0< / span > , < span class = "hljs-built_in" > len< / span > (ages))
< / code > < / pre >
< p > 在 上 面 的 第 一 個 range循 環 中 , 我 們 隻 關 心 map中 的 key, 所 以 我 們 忽 略 了 第 二 個 循 環 變 量 。 在 第 二 個 循 環 中 , 我 們 隻 關 繫 names中 的 名 字 , 所 以 我 們 使 用 “ _” 空 白 標 識 符 來 忽 略 第 一 個 循 環 變 量 , 也 就 是 迭 代 slice時 的 索 引 。 < / p >
< p > map類 型 的 零 值 是 nil, 也 就 是 沒 有 引 用 任 何 哈 希 表 。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > var< / span > ages < span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span >
fmt.Println(ages == < span class = "hljs-constant" > nil< / span > ) < span class = "hljs-comment" > // " true" < / span >
fmt.Println(< span class = "hljs-built_in" > len< / span > (ages) == < span class = "hljs-number" > 0< / span > ) < span class = "hljs-comment" > // " true" < / span >
< / code > < / pre >
< p > map上 的 大 部 分 操 作 , 包 括 査 找 、 刪 除 、 len和 range循 環 都 可 以 安 全 工 作 在 nil值 的 map上 , 它 們 的 行 爲 和 一 個 空 的 map類 似 。 但 是 向 一 個 nil值 的 map存 入 元 素 將 導 致 一 個 panic異 常 : < / p >
< pre > < code class = "lang-Go" > ages[< span class = "hljs-string" > " carol" < / span > ] = < span class = "hljs-number" > 21< / span > < span class = "hljs-comment" > // panic: assignment to entry in nil map< / span >
< / code > < / pre >
< p > 在 向 map存 數 據 前 必 鬚 先 創 建 map。 < / p >
< p > 通 過 key作 爲 索 引 下 標 來 訪 問 map將 産 生 一 個 value。 如 果 key在 map中 是 存 在 的 , 那 麽 將 得 到 與 key對 應 的 value; 如 果 key不 存 在 , 那 麽 將 得 到 value對 應 類 型 的 零 值 , 正 如 我 們 前 面 看 到 的 ages[" bob" ]那 樣 。 這 個 規 則 很 實 用 , 但 是 有 時 候 可 能 需 要 知 道 對 應 的 元 素 是 否 眞 的 是 在 map之 中 。 例 如 , 如 果 元 素 類 型 是 一 個 數 字 , 你 可 以 需 要 區 分 一 個 已 經 存 在 的 0, 和 不 存 在 而 返 迴 零 值 的 0, 可 以 像 下 面 這 樣 測 試 : < / p >
< pre > < code class = "lang-Go" > age, ok := ages[< span class = "hljs-string" > " bob" < / span > ]
< span class = "hljs-keyword" > if< / span > !ok { < span class = "hljs-comment" > /* " bob" is not a key in this map; age == 0. */< / span > }
< / code > < / pre >
< p > 你 會 經 常 看 到 將 這 兩 個 結 合 起 來 使 用 , 像 這 樣 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > if< / span > age, ok := ages[< span class = "hljs-string" > " bob" < / span > ]; !ok { < span class = "hljs-comment" > /* ... */< / span > }
< / code > < / pre >
< p > 在 這 種 場 景 下 , map的 下 標 語 法 將 産 生 兩 個 值 ; 第 二 個 是 一 個 布 爾 值 , 用 於 報 告 元 素 是 否 眞 的 存 在 。 布 爾 變 量 一 般 命 名 爲 ok, 特 别 適 合 馬 上 用 於 if條 件 判 斷 部 分 。 < / p >
< p > 和 slice一 樣 , map之 間 也 不 能 進 行 相 等 比 較 ; 唯 一 的 例 外 是 和 nil進 行 比 較 。 要 判 斷 兩 個 map是 否 包 含 相 同 的 key和 value, 我 們 必 鬚 通 過 一 個 循 環 實 現 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > equal(x, y < span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span > ) < span class = "hljs-typename" > bool< / span > {
< span class = "hljs-keyword" > if< / span > < span class = "hljs-built_in" > len< / span > (x) != < span class = "hljs-built_in" > len< / span > (y) {
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > false< / span >
}
< span class = "hljs-keyword" > for< / span > k, xv := < span class = "hljs-keyword" > range< / span > x {
< span class = "hljs-keyword" > if< / span > yv, ok := y[k]; !ok || yv != xv {
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > false< / span >
}
}
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > true< / span >
}
< / code > < / pre >
< p > 要 註 意 我 們 是 如 何 用 !ok來 區 分 元 素 缺 失 和 元 素 不 同 的 。 我 們 不 能 簡 單 地 用 xv != y[k]判 斷 , 那 樣 會 導 致 在 判 斷 下 面 兩 個 map時 産 生 錯 誤 的 結 果 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-comment" > // True if equal is written incorrectly.< / span >
equal(< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span > {< span class = "hljs-string" > " A" < / span > : < span class = "hljs-number" > 0< / span > }, < span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span > {< span class = "hljs-string" > " B" < / span > : < span class = "hljs-number" > 42< / span > })
< / code > < / pre >
< p > Go語 言 中 併 沒 有 提 供 一 個 set類 型 , 但 是 map中 的 key也 是 不 相 同 的 , 可 以 用 map實 現 類 似 的 功 能 。 爲 了 説 明 這 一 點 , 下 面 的 dedup程 序 讀 取 多 行 輸 入 , 但 是 隻 打 印 第 一 次 出 現 的 行 。 ( 它 是 1.3節 中 出 現 的 dup程 序 的 變 體 。 ) dedup程 序 通 過 map來 表 示 所 有 的 輸 入 行 所 對 應 的 set集 合 , 以 確 保 已 經 在 集 合 存 在 的 行 不 會 被 重 複 打 印 。 < / p >
< pre > < code class = "lang-Go" > gopl.io/ch4/dedup
< span class = "hljs-keyword" > func< / span > main() {
seen := < span class = "hljs-built_in" > make< / span > (< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > bool< / span > ) < span class = "hljs-comment" > // a set of strings< / span >
input := bufio.NewScanner(os.Stdin)
< span class = "hljs-keyword" > for< / span > input.Scan() {
line := input.Text()
< span class = "hljs-keyword" > if< / span > !seen[line] {
seen[line] = < span class = "hljs-constant" > true< / span >
fmt.Println(line)
}
}
< span class = "hljs-keyword" > if< / span > err := input.Err(); err != < span class = "hljs-constant" > nil< / span > {
fmt.Fprintf(os.Stderr, < span class = "hljs-string" > " dedup: %v\n" < / span > , err)
os.Exit(< span class = "hljs-number" > 1< / span > )
}
}
< / code > < / pre >
< p > Go程 序 員 將 這 種 忽 略 value的 map當 作 一 個 字 符 串 集 合 , 併 非 所 有 map[string]bool類 型 value都 是 無 關 緊 要 的 ; 有 一 些 則 可 能 會 同 時 包 含 tue和 false的 值 。 < / p >
< p > 有 時 候 我 們 需 要 一 個 map或 set的 key是 slice類 型 , 但 是 map的 key必 鬚 是 可 比 較 的 , 但 是 slice併 不 滿 足 這 個 條 件 。 不 過 , 我 們 可 以 通 過 兩 個 步 驟 繞 過 這 個 限 製 。 第 一 步 , 定 義 一 個 輔 助 函 數 k, 將 slice轉 爲 map對 應 的 string類 型 的 key, 確 保 隻 有 x和 y相 等 時 k(x) == k(y)才 成 立 。 然 後 創 建 一 個 key爲 string類 型 的 map, 在 每 次 對 map操 作 時 先 用 k輔 助 函 數 將 slice轉 化 爲 string類 型 。 < / p >
< p > 下 面 的 例 子 演 示 了 如 何 使 用 map來 記 録 提 交 相 同 的 字 符 串 列 表 的 次 數 。 它 使 用 了 fmt.Sprintf函 數 將 字 符 串 列 表 轉 換 爲 一 個 字 符 串 以 用 於 map的 key, 通 過 %q參 數 忠 實 地 記 録 每 個 字 符 串 元 素 的 信 息 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > var< / span > m = < span class = "hljs-built_in" > make< / span > (< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > int< / span > )
< span class = "hljs-keyword" > func< / span > k(list []< span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > string< / span > { < span class = "hljs-keyword" > return< / span > fmt.Sprintf(< span class = "hljs-string" > " %q" < / span > , list) }
< span class = "hljs-keyword" > func< / span > Add(list []< span class = "hljs-typename" > string< / span > ) { m[k(list)]++ }
< span class = "hljs-keyword" > func< / span > Count(list []< span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > int< / span > { < span class = "hljs-keyword" > return< / span > m[k(list)] }
< / code > < / pre >
< p > 使 用 同 樣 的 技 術 可 以 處 理 任 何 不 可 比 較 的 key類 型 , 而 不 僅 僅 是 slice類 型 。 它 對 於 想 使 用 自 定 義 key比 較 函 數 的 時 候 也 很 有 用 , 例 如 在 比 較 字 符 串 的 時 候 忽 略 大 小 寫 。 同 時 , 輔 助 函 數 k(x)也 不 一 定 是 字 符 串 類 型 , 它 可 以 返 迴 任 何 可 比 較 的 類 型 , 例 如 整 數 、 數 組 或 結 構 體 等 。 < / p >
< p > 這 是 map的 另 一 個 例 子 , 下 面 的 程 序 用 於 統 計 輸 入 中 每 個 Unicode碼 點 出 現 的 次 數 。 雖 然 Unicode全 部 碼 點 的 數 量 鉅 大 , 但 是 出 現 在 特 點 文 檔 中 的 字 符 併 沒 有 多 少 , 使 用 map可 以 用 比 較 自 然 的 方 式 來 跟 蹤 那 些 見 過 字 符 次 數 。 < / p >
< pre > < code class = "lang-Go" > gopl.io/ch4/charcount
< span class = "hljs-comment" > // Charcount computes counts of Unicode characters.< / span >
< span class = "hljs-keyword" > package< / span > main
< span class = "hljs-keyword" > import< / span > (
< span class = "hljs-string" > " bufio" < / span >
< span class = "hljs-string" > " fmt" < / span >
< span class = "hljs-string" > " io" < / span >
< span class = "hljs-string" > " os" < / span >
< span class = "hljs-string" > " unicode" < / span >
< span class = "hljs-string" > " unicode/utf8" < / span >
)
< span class = "hljs-keyword" > func< / span > main() {
counts := < span class = "hljs-built_in" > make< / span > (< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > rune< / span > ]< span class = "hljs-typename" > int< / span > ) < span class = "hljs-comment" > // counts of Unicode characters< / span >
< span class = "hljs-keyword" > var< / span > utflen [utf8.UTFMax + < span class = "hljs-number" > 1< / span > ]< span class = "hljs-typename" > int< / span > < span class = "hljs-comment" > // count of lengths of UTF-8 encodings< / span >
invalid := < span class = "hljs-number" > 0< / span > < span class = "hljs-comment" > // count of invalid UTF-8 characters< / span >
in := bufio.NewReader(os.Stdin)
< span class = "hljs-keyword" > for< / span > {
r, n, err := in.ReadRune() < span class = "hljs-comment" > // returns rune, nbytes, error< / span >
< span class = "hljs-keyword" > if< / span > err == io.EOF {
< span class = "hljs-keyword" > break< / span >
}
< span class = "hljs-keyword" > if< / span > err != < span class = "hljs-constant" > nil< / span > {
fmt.Fprintf(os.Stderr, < span class = "hljs-string" > " charcount: %v\n" < / span > , err)
os.Exit(< span class = "hljs-number" > 1< / span > )
}
< span class = "hljs-keyword" > if< / span > r == unicode.ReplacementChar & & n == < span class = "hljs-number" > 1< / span > {
invalid++
< span class = "hljs-keyword" > continue< / span >
}
counts[r]++
utflen[n]++
}
fmt.Printf(< span class = "hljs-string" > " rune\tcount\n" < / span > )
< span class = "hljs-keyword" > for< / span > c, n := < span class = "hljs-keyword" > range< / span > counts {
fmt.Printf(< span class = "hljs-string" > " %q\t%d\n" < / span > , c, n)
}
fmt.Print(< span class = "hljs-string" > " \nlen\tcount\n" < / span > )
< span class = "hljs-keyword" > for< / span > i, n := < span class = "hljs-keyword" > range< / span > utflen {
< span class = "hljs-keyword" > if< / span > i > < span class = "hljs-number" > 0< / span > {
fmt.Printf(< span class = "hljs-string" > " %d\t%d\n" < / span > , i, n)
}
}
< span class = "hljs-keyword" > if< / span > invalid > < span class = "hljs-number" > 0< / span > {
fmt.Printf(< span class = "hljs-string" > " \n%d invalid UTF-8 characters\n" < / span > , invalid)
}
}
< / code > < / pre >
< p > ReadRune方 法 執 行 UTF-8解 碼 併 返 迴 三 個 值 : 解 碼 的 rune字 符 的 值 , 字 符 UTF-8編 碼 後 的 長 度 , 和 一 個 錯 誤 值 。 我 們 可 預 期 的 錯 誤 值 隻 有 對 應 文 件 結 尾 的 io.EOF。 如 果 輸 入 的 是 無 效 的 UTF-8編 碼 的 字 符 , 返 迴 的 將 是 unicode.ReplacementChar無 效 字 符 , 併 且 編 碼 長 度 是 1。 < / p >
< p > charcount程 序 同 時 打 印 不 同 UTF-8編 碼 長 度 的 字 符 數 目 。 對 此 , map併 不 是 一 個 合 適 的 數 據 結 構 ; 因 爲 UTF-8編 碼 的 長 度 總 是 從 1到 utf8.UTFMax( 最 大 是 4個 字 節 ) , 使 用 數 組 將 更 有 效 。 < / p >
< p > 作 爲 一 個 實 驗 , 我 們 用 charcount程 序 對 本 身 的 字 符 進 行 了 統 計 。 雖 然 大 部 分 是 英 語 , 但 是 也 有 一 些 非 ASCII字 符 。 下 面 是 排 名 前 10的 非 ASCII字 符 : < / p >
< p > < img src = "../images/ch4-xx-01.png" alt = "" > < / p >
< p > 下 面 是 不 同 UTF-8編 碼 長 度 的 字 符 的 數 目 : < / p >
< pre > < code > len count
1 765391
2 60
3 70
4 0
< / code > < / pre > < p > Map的 value類 型 也 可 以 是 一 個 聚 合 類 型 , 比 如 是 一 個 map或 slice。 在 下 面 的 代 碼 中 , 圖 graph的 key類 型 是 一 個 字 符 串 , value類 型 map[string]bool代 表 一 個 字 符 串 集 合 。 從 概 念 上 將 , graph將 一 個 字 符 串 類 型 的 key映 射 到 一 組 相 關 的 字 符 串 集 合 , 它 們 指 向 新 的 graph的 key。 < / p >
< pre > < code class = "lang-Go" > gopl.io/ch4/graph
< span class = "hljs-keyword" > var< / span > graph = < span class = "hljs-built_in" > make< / span > (< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > bool< / span > )
< span class = "hljs-keyword" > func< / span > addEdge(from, to < span class = "hljs-typename" > string< / span > ) {
edges := graph[from]
< span class = "hljs-keyword" > if< / span > edges == < span class = "hljs-constant" > nil< / span > {
edges = < span class = "hljs-built_in" > make< / span > (< span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > bool< / span > )
graph[from] = edges
}
edges[to] = < span class = "hljs-constant" > true< / span >
}
< span class = "hljs-keyword" > func< / span > hasEdge(from, to < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > bool< / span > {
< span class = "hljs-keyword" > return< / span > graph[from][to]
}
< / code > < / pre >
< p > 其 中 addEdge函 數 惰 性 初 始 化 map是 一 個 慣 用 方 式 , 也 就 是 説 在 每 個 值 首 次 作 爲 key是 才 初 始 化 。 addEdge函 數 顯 示 了 如 何 讓 map的 零 值 也 能 正 常 工 作 ; 卽 使 from到 to的 邊 不 存 在 , graph[from][to]依 然 可 以 返 迴 一 個 有 意 義 的 結 果 。 < / p >
< p > < strong > 練 習 4.8: < / strong > 脩 改 charcount程 序 , 使 用 unicode.IsLetter等 相 關 的 函 數 , 統 計 字 母 、 數 字 等 Unicode中 不 同 的 字 符 類 别 。 < / p >
< p > < strong > 練 習 4.9: < / strong > 編 寫 一 個 程 序 wordfreq程 序 , 報 告 輸 入 文 本 中 每 個 單 詞 出 現 的 頻 率 。 在 第 一 次 調 用 Scan前 先 調 用 input.Split(bufio.ScanWords)函 數 , 這 樣 可 以 按 單 詞 而 不 是 按 行 輸 入 。 < / p >
2015-12-09 07:57:17 +00:00
< / section >
< / div >
< / div >
< / div >
2015-12-31 08:20:27 +00:00
< a href = "../ch4/ch4-02.html" class = "navigation navigation-prev " aria-label = "Previous page: Slice" > < i class = "fa fa-angle-left" > < / i > < / a >
2015-12-09 07:57:17 +00:00
< a href = "../ch4/ch4-04.html" class = "navigation navigation-next " aria-label = "Next page: 結構體" > < i class = "fa fa-angle-right" > < / i > < / a >
< / div >
< / div >
< script src = "../gitbook/app.js" > < / script >
< script src = "../gitbook/plugins/gitbook-plugin-sharing/buttons.js" > < / script >
< script src = "../gitbook/plugins/gitbook-plugin-fontsettings/buttons.js" > < / script >
< script >
require(["gitbook"], function(gitbook) {
2015-12-28 08:08:26 +00:00
var config = {"katex":{},"highlight":{},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2}};
2015-12-09 07:57:17 +00:00
gitbook.start(config);
});
< / script >
< / body >
< / html >