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 > 字符串 | 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 = "" >
2016-01-02 08:04:45 +00:00
< meta name = "generator" content = "GitBook 2.6.6" >
2015-12-09 07:57:17 +00:00
< 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 = "../ch3/ch3-06.html" / >
< link rel = "prev" href = "../ch3/ch3-04.html" / >
< / head >
< body >
2016-01-02 08:04:45 +00:00
< div class = "book"
data-level="3.5"
data-chapter-title="字符串"
data-filepath="ch3/ch3-05.md"
data-basepath=".."
data-revision="Sat Jan 02 2016 16:00:23 GMT+0800 (中国标准时间)"
data-innerlanguage="">
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 active" 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 " 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-" >
< h2 id = "35-字符串" > 3.5. 字 符 串 < / h2 >
2015-12-28 08:08:26 +00:00
< p > 一 個 字 符 串 是 一 個 不 可 改 變 的 字 節 序 列 。 字 符 串 可 以 包 含 任 意 的 數 據 , 包 括 byte值 0, 但 是 通 常 是 用 來 包 含 人 類 可 讀 的 文 本 。 文 本 字 符 串 通 常 被 解 釋 爲 采 用 UTF8編 碼 的 Unicode碼 點 ( rune) 序 列 , 我 們 稍 後 會 詳 細 討 論 這 個 問 題 。 < / p >
< p > 內 置 的 len函 數 可 以 返 迴 一 個 字 符 串 中 的 字 節 數 目 ( 不 是 rune字 符 數 目 ) , 索 引 操 作 s[i]返 迴 第 i個 字 節 的 字 節 值 , i必 鬚 滿 足 0 ≤ i< len(s)條 件 約 束 。 < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > s := < span class = "hljs-string" > " hello, world" < / span >
fmt.Println(< span class = "hljs-built_in" > len< / span > (s)) < span class = "hljs-comment" > // " 12" < / span >
fmt.Println(s[< span class = "hljs-number" > 0< / span > ], s[< span class = "hljs-number" > 7< / span > ]) < span class = "hljs-comment" > // " 104 119" (' h' and ' w' )< / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 如 果 試 圖 訪 問 超 出 字 符 串 索 引 范 圍 的 字 節 將 會 導 致 panic異 常 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > c := s[< span class = "hljs-built_in" > len< / span > (s)] < span class = "hljs-comment" > // panic: index out of range< / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 第 i個 字 節 併 不 一 定 是 字 符 串 的 第 i個 字 符 , 因 爲 對 於 非 ASCII字 符 的 UTF8編 碼 會 要 兩 個 或 多 個 字 節 。 我 們 先 簡 單 説 下 字 符 的 工 作 方 式 。 < / p >
< p > 子 字 符 串 操 作 s[i:j]基 於 原 始 的 s字 符 串 的 第 i個 字 節 開 始 到 第 j個 字 節 ( 併 不 包 含 j本 身 ) 生 成 一 個 新 字 符 串 。 生 成 的 新 字 符 串 將 包 含 j-i個 字 節 。 < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(s[< span class = "hljs-number" > 0< / span > :< span class = "hljs-number" > 5< / span > ]) < span class = "hljs-comment" > // " hello" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 同 樣 , 如 果 索 引 超 出 字 符 串 范 圍 或 者 j小 於 i的 話 將 導 致 panic異 常 。 < / p >
< p > 不 管 i還 是 j都 可 能 被 忽 略 , 當 它 們 被 忽 略 時 將 采 用 0作 爲 開 始 位 置 , 采 用 len(s)作 爲 結 束 的 位 置 。 < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(s[:< span class = "hljs-number" > 5< / span > ]) < span class = "hljs-comment" > // " hello" < / span >
fmt.Println(s[< span class = "hljs-number" > 7< / span > :]) < span class = "hljs-comment" > // " world" < / span >
fmt.Println(s[:]) < span class = "hljs-comment" > // " hello, world" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 其 中 +操 作 符 將 兩 個 字 符 串 鏈 接 構 造 一 個 新 字 符 串 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(< span class = "hljs-string" > " goodbye" < / span > + s[< span class = "hljs-number" > 5< / span > :]) < span class = "hljs-comment" > // " goodbye, world" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 字 符 串 可 以 用 ==和 < 進 行 比 較 ; 比 較 通 過 逐 個 字 節 比 較 完 成 的 , 因 此 比 較 的 結 果 是 字 符 串 自 然 編 碼 的 順 序 。 < / p >
< p > 字 符 串 的 值 是 不 可 變 的 : 一 個 字 符 串 包 含 的 字 節 序 列 永 遠 不 會 被 改 變 , 當 然 我 們 也 可 以 給 一 個 字 符 串 變 量 分 配 一 個 新 字 符 串 值 。 可 以 像 下 面 這 樣 將 一 個 字 符 串 追 加 到 另 一 個 字 符 串 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > s := < span class = "hljs-string" > " left foot" < / span >
t := s
s += < span class = "hljs-string" > " , right foot" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 這 併 不 會 導 致 原 始 的 字 符 串 值 被 改 變 , 但 是 變 量 s將 因 爲 +=語 句 持 有 一 個 新 的 字 符 串 值 , 但 是 t依 然 是 包 含 原 先 的 字 符 串 值 。 < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(s) < span class = "hljs-comment" > // " left foot, right foot" < / span >
fmt.Println(t) < span class = "hljs-comment" > // " left foot" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 因 爲 字 符 串 是 不 可 脩 改 的 , 因 此 嚐 試 脩 改 字 符 串 內 部 數 據 的 操 作 也 是 被 禁 止 的 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > s[< span class = "hljs-number" > 0< / span > ] = < span class = "hljs-string" > ' L' < / span > < span class = "hljs-comment" > // compile error: cannot assign to s[0]< / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 不 變 性 意 味 如 果 兩 個 字 符 串 共 享 相 同 的 底 層 數 據 的 話 也 是 安 全 的 , 這 使 得 複 製 任 何 長 度 的 字 符 串 代 價 是 低 廉 的 。 同 樣 , 一 個 字 符 串 s和 對 應 的 子 字 符 串 切 片 s[7:]的 操 作 也 可 以 安 全 地 共 享 相 同 的 內 存 , 因 此 字 符 串 切 片 操 作 代 價 也 是 低 廉 的 。 在 這 兩 種 情 況 下 都 沒 有 必 要 分 配 新 的 內 存 。 圖 3.4演 示 了 一 個 字 符 串 和 兩 個 字 串 共 享 相 同 的 底 層 數 據 。 < / p >
2015-12-21 04:55:18 +00:00
< h3 id = "351-字符串面值" > 3.5.1. 字 符 串 面 值 < / h3 >
2015-12-28 08:08:26 +00:00
< p > 字 符 串 值 也 可 以 用 字 符 串 面 值 方 式 編 寫 , 隻 要 將 一 繫 列 字 節 序 列 包 含 在 雙 引 號 卽 可 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code > " Hello, 世 界 "
< / code > < / pre > < p > < img src = "../images/ch3-04.png" alt = "" > < / p >
2015-12-28 08:08:26 +00:00
< p > 因 爲 Go語 言 源 文 件 總 是 用 UTF8編 碼 , 併 且 Go語 言 的 文 本 字 符 串 也 以 UTF8編 碼 的 方 式 處 理 , 因 此 我 們 可 以 將 Unicode碼 點 也 寫 到 字 符 串 面 值 中 。 < / p >
< p > 在 一 個 雙 引 號 包 含 的 字 符 串 面 值 中 , 可 以 用 以 反 斜 槓 < code > \< / code > 開 頭 的 轉 義 序 列 插 入 任 意 的 數 據 。 下 面 的 換 行 、 迴 車 和 製 表 符 等 是 常 見 的 ASCII控 製 代 碼 的 轉 義 方 式 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code > \a 響 鈴
\b 退 格
\f 換 頁
\n 換 行
\r 迴 車
\t 製 表 符
\v 垂 直 製 表 符
\' 單 引 號 (隻 用 在 ' \' ' 形 式 的 rune符 號 面 值 中 )
\" 雙 引 號 (隻 用 在 " ..." 形 式 的 字 符 串 面 值 中 )
\\ 反 斜 槓
2015-12-28 08:08:26 +00:00
< / code > < / pre > < p > 可 以 通 過 十 六 進 製 或 八 進 製 轉 義 在 字 符 串 面 值 包 含 任 意 的 字 節 。 一 個 十 六 進 製 的 轉 義 形 式 是 \xhh, 其 中 兩 個 h表 示 十 六 進 製 數 字 ( 大 寫 或 小 寫 都 可 以 ) 。 一 個 八 進 製 轉 義 形 式 是 \ooo, 包 含 三 個 八 進 製 的 o數 字 ( 0到 7) , 但 是 不 能 超 過 < code > \377< / code > ( 譯 註 : 對 應 一 個 字 節 的 范 圍 , 十 進 製 爲 255) 。 每 一 個 單 一 的 字 節 表 達 一 個 特 定 的 值 。 稍 後 我 們 將 看 到 如 何 將 一 個 Unicode碼 點 寫 到 字 符 串 面 值 中 。 < / p >
< p > 一 個 原 生 的 字 符 串 面 值 形 式 是 < code > ...< / code > , 使 用 反 引 號 < code > 代 替 雙 引 號 。 在 原 生 的 字 符 串 面 值 中 , 沒 有 轉 義 操 作 ; 全 部 的 內 容 都 是 字 面 的 意 思 , 包 含 退 格 和 換 行 , 因 此 一 個 程 序 中 的 原 生 字 符 串 面 值 可 能 跨 越 多 行 ( 譯 註 : 在 原 生 字 符 串 面 值 內 部 是 無 法 直 接 寫 < / code > 字 符 的 , 可 以 用 八 進 製 或 十 六 進 製 轉 義 或 +" ```" 鏈 接 字 符 串 常 量 完 成 ) 。 唯 一 的 特 殊 處 理 是 會 刪 除 迴 車 以 保 證 在 所 有 平 台 上 的 值 都 是 一 樣 的 , 包 括 那 些 把 迴 車 也 放 入 文 本 文 件 的 繫 統 ( 譯 註 : Windows繫 統 會 把 迴 車 和 換 行 一 起 放 入 文 本 文 件 中 ) 。 < / p >
< p > 原 生 字 符 串 面 值 用 於 編 寫 正 則 表 達 式 會 很 方 便 , 因 爲 正 則 表 達 式 往 往 會 包 含 很 多 反 斜 槓 。 原 生 字 符 串 面 值 同 時 被 廣 泛 應 用 於 HTML模 闆 、 JSON面 值 、 命 令 行 提 示 信 息 以 及 那 些 需 要 擴 展 到 多 行 的 場 景 。 < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > const< / span > GoUsage = < span class = "hljs-string" > `Go is a tool for managing Go source code.
Usage:
go command [arguments]
...`< / span >
< / code > < / pre >
< h3 id = "352-unicode" > 3.5.2. Unicode< / h3 >
2015-12-28 08:08:26 +00:00
< p > 在 很 久 以 前 , 世 界 還 是 比 較 簡 單 的 , 起 碼 計 算 機 世 界 就 隻 有 一 個 ASCII字 符 集 : 美 国 信 息 交 換 標 準 代 碼 。 ASCII, 更 準 確 地 説 是 美 国 的 ASCII, 使 用 7bit來 表 示 128個 字 符 : 包 含 英 文 字 母 的 大 小 寫 、 數 字 、 各 種 標 點 符 號 和 設 置 控 製 符 。 對 於 早 期 的 計 算 機 程 序 來 説 , 這 些 就 足 夠 了 , 但 是 這 也 導 致 了 世 界 上 很 多 其 他 地 區 的 用 戶 無 法 直 接 使 用 自 己 的 符 號 繫 統 。 隨 着 互 聯 網 的 發 展 , 混 合 多 種 語 言 的 數 據 變 得 很 常 見 ( 譯 註 : 比 如 本 身 的 英 文 原 文 或 中 文 翻 譯 都 包 含 了 ASCII、 中 文 、 日 文 等 多 種 語 言 字 符 ) 。 如 何 有 效 處 理 這 些 包 含 了 各 種 語 言 的 豐 富 多 樣 的 文 本 數 據 呢 ? < / p >
< p > 答 案 就 是 使 用 Unicode( < a href = "http://unicode.org" target = "_blank" > http://unicode.org< / a > ) , 它 收 集 了 這 個 世 界 上 所 有 的 符 號 繫 統 , 包 括 重 音 符 號 和 其 它 變 音 符 號 , 製 表 符 和 迴 車 符 , 還 有 很 多 神 祕 的 符 號 , 每 個 符 號 都 分 配 一 個 唯 一 的 Unicode碼 點 , Unicode碼 點 對 應 Go語 言 中 的 rune整 數 類 型 ( 譯 註 : rune是 int32等 價 類 型 ) 。 < / p >
< p > 在 第 八 版 本 的 Unicode標 準 收 集 了 超 過 120,000個 字 符 , 涵 蓋 超 過 100多 種 語 言 。 這 些 在 計 算 機 程 序 和 數 據 中 是 如 何 體 現 的 呢 ? 通 用 的 表 示 一 個 Unicode碼 點 的 數 據 類 型 是 int32, 也 就 是 Go語 言 中 rune對 應 的 類 型 ; 它 的 同 義 詞 rune符 文 正 是 這 個 意 思 。 < / p >
< p > 我 們 可 以 將 一 個 符 文 序 列 表 示 爲 一 個 int32序 列 。 這 種 編 碼 方 式 叫 UTF-32或 UCS-4, 每 個 Unicode碼 點 都 使 用 同 樣 的 大 小 32bit來 表 示 。 這 種 方 式 比 較 簡 單 統 一 , 但 是 它 會 浪 費 很 多 存 儲 空 間 , 因 爲 大 數 據 計 算 機 可 讀 的 文 本 是 ASCII字 符 , 本 來 每 個 ASCII字 符 隻 需 要 8bit或 1字 節 就 能 表 示 。 而 且 卽 使 是 常 用 的 字 符 也 遠 少 於 65,536個 , 也 就 是 説 用 16bit編 碼 方 式 就 能 表 達 常 用 字 符 。 但 是 , 還 有 其 它 更 好 的 編 碼 方 法 嗎 ? < / p >
2015-12-21 04:55:18 +00:00
< h3 id = "353-utf8" > 3.5.3. UTF-8< / h3 >
2015-12-28 08:08:26 +00:00
< p > UTF8是 一 個 將 Unicode碼 點 編 碼 爲 字 節 序 列 的 變 長 編 碼 。 UTF8編 碼 由 Go語 言 之 父 Ken Thompson和 Rob Pike共 同 發 明 的 , 現 在 已 經 是 Unicode的 標 準 。 UTF8編 碼 使 用 1到 4個 字 節 來 表 示 每 個 Unicode碼 點 , ASCII部 分 字 符 隻 使 用 1個 字 節 , 常 用 字 符 部 分 使 用 2或 3個 字 節 表 示 。 每 個 符 號 編 碼 後 第 一 個 字 節 的 高 端 bit位 用 於 表 示 總 共 有 多 少 編 碼 個 字 節 。 如 果 第 一 個 字 節 的 高 端 bit爲 0, 則 表 示 對 應 7bit的 ASCII字 符 , ASCII字 符 每 個 字 符 依 然 是 一 個 字 節 , 和 傳 統 的 ASCII編 碼 兼 容 。 如 果 第 一 個 字 節 的 高 端 bit是 110, 則 説 明 需 要 2個 字 節 ; 後 續 的 每 個 高 端 bit都 以 10開 頭 。 更 大 的 Unicode碼 點 也 是 采 用 類 似 的 策 略 處 理 。 < / p >
2015-12-24 06:47:06 +00:00
< pre > < code > 0xxxxxxx runes 0-127 (ASCII)
110xxxxx 10xxxxxx 128-2047 (values < 128 unused)
1110xxxx 10xxxxxx 10xxxxxx 2048-65535 (values < 2048 unused)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 65536-0x10ffff (other values unused)
2015-12-28 08:08:26 +00:00
< / code > < / pre > < p > 變 長 的 編 碼 無 法 直 接 通 過 索 引 來 訪 問 第 n個 字 符 , 但 是 UTF8編 碼 獲 得 了 很 多 額 外 的 優 點 。 首 先 UTF8編 碼 比 較 緊 湊 , 完 全 兼 容 ASCII碼 , 併 且 可 以 自 動 同 步 : 它 可 以 通 過 向 前 迴 朔 最 多 2個 字 節 就 能 確 定 當 前 字 符 編 碼 的 開 始 字 節 的 位 置 。 它 也 是 一 個 前 綴 編 碼 , 所 以 當 從 左 向 右 解 碼 時 不 會 有 任 何 歧 義 也 併 不 需 要 向 前 査 看 ( 譯 註 : 像 GBK之 類 的 編 碼 , 如 果 不 知 道 起 點 位 置 則 可 能 會 出 現 歧 義 ) 。 沒 有 任 何 字 符 的 編 碼 是 其 它 字 符 編 碼 的 子 串 , 或 是 其 它 編 碼 序 列 的 字 串 , 因 此 蒐 索 一 個 字 符 時 隻 要 蒐 索 它 的 字 節 編 碼 序 列 卽 可 , 不 用 擔 心 前 後 的 上 下 文 會 對 蒐 索 結 果 産 生 榦 擾 。 同 時 UTF8編 碼 的 順 序 和 Unicode碼 點 的 順 序 一 致 , 因 此 可 以 直 接 排 序 UTF8編 碼 序 列 。 同 時 因 爲 沒 有 嵌 入 的 NUL(0)字 節 , 可 以 很 好 地 兼 容 那 些 使 用 NUL作 爲 字 符 串 結 尾 的 編 程 語 言 。 < / p >
< p > Go語 言 的 源 文 件 采 用 UTF8編 碼 , 併 且 Go語 言 處 理 UTF8編 碼 的 文 本 也 很 出 色 。 unicode包 提 供 了 諸 多 處 理 rune字 符 相 關 功 能 的 函 數 ( 比 如 區 分 字 母 和 數 組 , 或 者 是 字 母 的 大 寫 和 小 寫 轉 換 等 ) , unicode/utf8包 則 提 供 了 用 於 rune字 符 序 列 的 UTF8編 碼 和 解 碼 的 功 能 。 < / p >
< p > 有 很 多 Unicode字 符 很 難 直 接 從 鍵 盤 輸 入 , 併 且 還 有 很 多 字 符 有 着 相 似 的 結 構 ; 有 一 些 甚 至 是 不 可 見 的 字 符 ( 譯 註 : 中 文 和 日 文 就 有 很 多 相 似 但 不 同 的 字 ) 。 Go語 言 字 符 串 面 值 中 的 Unicode轉 義 字 符 讓 我 們 可 以 通 過 Unicode碼 點 輸 入 特 殊 的 字 符 。 有 兩 種 形 式 : \uhhhh對 應 16bit的 碼 點 值 , \Uhhhhhhhh對 應 32bit的 碼 點 值 , 其 中 h是 一 個 十 六 進 製 數 字 ; 一 般 很 少 需 要 使 用 32bit的 形 式 。 每 一 個 對 應 碼 點 的 UTF8編 碼 。 例 如 : 下 面 的 字 母 串 面 值 都 表 示 相 同 的 值 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code > " 世 界 "
" \xe4\xb8\x96\xe7\x95\x8c"
" \u4e16\u754c"
" \U00004e16\U0000754c"
2015-12-28 08:08:26 +00:00
< / code > < / pre > < p > 上 面 三 個 轉 義 序 列 都 爲 第 一 個 字 符 串 提 供 替 代 寫 法 , 但 是 它 們 的 值 都 是 相 同 的 。 < / p >
< p > Unicode轉 義 也 可 以 使 用 在 rune字 符 中 。 下 面 三 個 字 符 是 等 價 的 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code > ' 世 ' ' \u4e16' ' \U00004e16'
2015-12-28 08:08:26 +00:00
< / code > < / pre > < p > 對 於 小 於 256碼 點 值 可 以 寫 在 一 個 十 六 進 製 轉 義 字 節 中 , 例 如 ' \x41' 對 應 字 符 ' A' , 但 是 對 於 更 大 的 碼 點 則 必 鬚 使 用 \u或 \U轉 義 形 式 。 因 此 , ' \xe4\xb8\x96' 併 不 是 一 個 合 法 的 rune字 符 , 雖 然 這 三 個 字 節 對 應 一 個 有 效 的 UTF8編 碼 的 碼 點 。 < / p >
< p > 得 益 於 UTF8編 碼 優 良 的 設 計 , 諸 多 字 符 串 操 作 都 不 需 要 解 碼 操 作 。 我 們 可 以 不 用 解 碼 直 接 測 試 一 個 字 符 串 是 否 是 另 一 個 字 符 串 的 前 綴 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > HasPrefix(s, prefix < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > bool< / span > {
< span class = "hljs-keyword" > return< / span > < span class = "hljs-built_in" > len< / span > (s) > = < span class = "hljs-built_in" > len< / span > (prefix) & & s[:< span class = "hljs-built_in" > len< / span > (prefix)] == prefix
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 或 者 是 後 綴 測 試 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > HasSuffix(s, suffix < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > bool< / span > {
< span class = "hljs-keyword" > return< / span > < span class = "hljs-built_in" > len< / span > (s) > = < span class = "hljs-built_in" > len< / span > (suffix) & & s[< span class = "hljs-built_in" > len< / span > (s)-< span class = "hljs-built_in" > len< / span > (suffix):] == suffix
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 或 者 是 包 含 子 串 測 試 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > Contains(s, substr < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > bool< / span > {
< span class = "hljs-keyword" > for< / span > i := < span class = "hljs-number" > 0< / span > ; i < < span class = "hljs-built_in" > len< / span > (s); i++ {
< span class = "hljs-keyword" > if< / span > HasPrefix(s[i:], substr) {
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > true< / span >
}
}
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > false< / span >
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 對 於 UTF8編 碼 後 文 本 的 處 理 和 原 始 的 字 節 處 理 邏 輯 是 一 樣 的 。 但 是 對 應 很 多 其 它 編 碼 則 併 不 是 這 樣 的 。 ( 上 面 的 函 數 都 來 自 strings字 符 串 處 理 包 , 眞 實 的 代 碼 包 含 了 一 個 用 哈 希 技 術 優 化 的 Contains 實 現 。 ) < / p >
< p > 另 一 方 面 , 如 果 我 們 眞 的 關 心 每 個 Unicode字 符 , 我 們 可 以 使 用 其 它 處 理 方 式 。 考 慮 前 面 的 第 一 個 例 子 中 的 字 符 串 , 它 包 混 合 了 中 西 兩 種 字 符 。 圖 3.5展 示 了 它 的 內 存 表 示 形 式 。 字 符 串 包 含 13個 字 節 , 以 UTF8形 式 編 碼 , 但 是 隻 對 應 9個 Unicode字 符 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > import< / span > < span class = "hljs-string" > " unicode/utf8" < / span >
s := < span class = "hljs-string" > " Hello, 世 界 " < / span >
fmt.Println(< span class = "hljs-built_in" > len< / span > (s)) < span class = "hljs-comment" > // " 13" < / span >
fmt.Println(utf8.RuneCountInString(s)) < span class = "hljs-comment" > // " 9" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 爲 了 處 理 這 些 眞 實 的 字 符 , 我 們 需 要 一 個 UTF8解 碼 器 。 unicode/utf8包 提 供 了 該 功 能 , 我 們 可 以 這 樣 使 用 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > for< / span > i := < span class = "hljs-number" > 0< / span > ; i < < span class = "hljs-built_in" > len< / span > (s); {
r, size := utf8.DecodeRuneInString(s[i:])
fmt.Printf(< span class = "hljs-string" > " %d\t%c\n" < / span > , i, r)
i += size
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 每 一 次 調 用 DecodeRuneInString函 數 都 返 迴 一 個 r和 長 度 , r對 應 字 符 本 身 , 長 度 對 應 r采 用 UTF8編 碼 後 的 編 碼 字 節 數 目 。 長 度 可 以 用 於 更 新 第 i個 字 符 在 字 符 串 中 的 字 節 索 引 位 置 。 但 是 這 種 編 碼 方 式 是 笨 拙 的 , 我 們 需 要 更 簡 潔 的 語 法 。 幸 運 的 是 , Go語 言 的 range循 環 在 處 理 字 符 串 的 時 候 , 會 自 動 隱 式 解 碼 UTF8字 符 串 。 下 面 的 循 環 運 行 如 圖 3.5所 示 ; 需 要 註 意 的 是 對 於 非 ASCII, 索 引 更 新 的 步 長 將 超 過 1個 字 節 。 < / p >
2015-12-21 04:55:18 +00:00
< p > < img src = "../images/ch3-05.png" alt = "" > < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > for< / span > i, r := < span class = "hljs-keyword" > range< / span > < span class = "hljs-string" > " Hello, 世 界 " < / span > {
fmt.Printf(< span class = "hljs-string" > " %d\t%q\t%d\n" < / span > , i, r, r)
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 我 們 可 以 使 用 一 個 簡 單 的 循 環 來 統 計 字 符 串 中 字 符 的 數 目 , 像 這 樣 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > n := < span class = "hljs-number" > 0< / span >
< span class = "hljs-keyword" > for< / span > _, _ = < span class = "hljs-keyword" > range< / span > s {
n++
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 像 其 它 形 式 的 循 環 那 樣 , 我 們 也 可 以 忽 略 不 需 要 的 變 量 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > n := < span class = "hljs-number" > 0< / span >
< span class = "hljs-keyword" > for< / span > < span class = "hljs-keyword" > range< / span > s {
n++
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 或 者 我 們 可 以 直 接 調 用 utf8.RuneCountInString(s)函 數 。 < / p >
< p > 正 如 我 們 前 面 提 到 的 , 文 本 字 符 串 采 用 UTF8編 碼 隻 是 一 種 慣 例 , 但 是 對 於 循 環 的 眞 正 字 符 串 併 不 是 一 個 慣 例 , 這 是 正 確 的 。 如 果 用 於 循 環 的 字 符 串 隻 是 一 個 普 通 的 二 進 製 數 據 , 或 者 是 含 有 錯 誤 編 碼 的 UTF8數 據 , 將 會 發 送 什 麽 呢 ? < / p >
< p > 每 一 個 UTF8字 符 解 碼 , 不 管 是 顯 式 地 調 用 utf8.DecodeRuneInString解 碼 或 是 在 range循 環 中 隱 式 地 解 碼 , 如 果 遇 到 一 個 錯 誤 的 UTF8編 碼 輸 入 , 將 生 成 一 個 特 别 的 Unicode字 符 ' \uFFFD' , 在 印 刷 中 這 個 符 號 通 常 是 一 個 黑 色 六 角 或 鑽 石 形 狀 , 里 面 包 含 一 個 白 色 的 問 號 ( ?) 。 當 程 序 遇 到 這 樣 的 一 個 字 符 , 通 常 是 一 個 危 險 信 號 , 説 明 輸 入 併 不 是 一 個 完 美 沒 有 錯 誤 的 UTF8字 符 串 。 < / p >
< p > UTF8字 符 串 作 爲 交 換 格 式 是 非 常 方 便 的 , 但 是 在 程 序 內 部 采 用 rune序 列 可 能 更 方 便 , 因 爲 rune大 小 一 致 , 支 持 數 組 索 引 和 方 便 切 割 。 < / p >
< p > string接 受 到 []rune的 類 型 轉 換 , 可 以 將 一 個 UTF8編 碼 的 字 符 串 解 碼 爲 Unicode字 符 序 列 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-comment" > // " program" in Japanese katakana< / span >
s := < span class = "hljs-string" > " プ ロ グ ラ ム " < / span >
fmt.Printf(< span class = "hljs-string" > " % x\n" < / span > , s) < span class = "hljs-comment" > // " e3 83 97 e3 83 ad e3 82 b0 e3 83 a9 e3 83 a0" < / span >
r := []< span class = "hljs-typename" > rune< / span > (s)
fmt.Printf(< span class = "hljs-string" > " %x\n" < / span > , r) < span class = "hljs-comment" > // " [30d7 30ed 30b0 30e9 30e0]" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > ( 在 第 一 個 Printf中 的 < code > % x< / code > 參 數 用 於 在 每 個 十 六 進 製 數 字 前 插 入 一 個 空 格 。 ) < / p >
< p > 如 果 是 將 一 個 []rune類 型 的 Unicode字 符 slice或 數 組 轉 爲 string, 則 對 它 們 進 行 UTF8編 碼 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(< span class = "hljs-typename" > string< / span > (r)) < span class = "hljs-comment" > // " プ ロ グ ラ ム " < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 將 一 個 整 數 轉 型 爲 字 符 串 意 思 是 生 成 以 隻 包 含 對 應 Unicode碼 點 字 符 的 UTF8字 符 串 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(< span class = "hljs-typename" > string< / span > (< span class = "hljs-number" > 65< / span > )) < span class = "hljs-comment" > // " A" , not " 65" < / span >
fmt.Println(< span class = "hljs-typename" > string< / span > (< span class = "hljs-number" > 0x4eac< / span > )) < span class = "hljs-comment" > // " 京 " < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 如 果 對 應 碼 點 的 字 符 是 無 效 的 , 則 用 ' \uFFFD' 無 效 字 符 作 爲 替 換 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(< span class = "hljs-typename" > string< / span > (< span class = "hljs-number" > 1234567< / span > )) < span class = "hljs-comment" > // " (?)" < / span >
< / code > < / pre >
< h3 id = "354-字符串和byte切片" > 3.5.4. 字 符 串 和 Byte切 片 < / h3 >
2015-12-28 08:08:26 +00:00
< p > 標 準 庫 中 有 四 個 包 對 字 符 串 處 理 尤 爲 重 要 : bytes、 strings、 strconv和 unicode包 。 strings包 提 供 了 許 多 如 字 符 串 的 査 詢 、 替 換 、 比 較 、 截 斷 、 拆 分 和 合 併 等 功 能 。 < / p >
< p > bytes包 也 提 供 了 很 多 類 似 功 能 的 函 數 , 但 是 針 對 和 字 符 串 有 着 相 同 結 構 的 []byte類 型 。 因 爲 字 符 串 是 隻 讀 的 , 因 此 逐 步 構 建 字 符 串 會 導 致 很 多 分 配 和 複 製 。 在 這 種 情 況 下 , 使 用 bytes.Buffer類 型 將 會 更 有 效 , 稍 後 我 們 將 展 示 。 < / p >
< p > strconv包 提 供 了 布 爾 型 、 整 型 數 、 浮 點 數 和 對 應 字 符 串 的 相 互 轉 換 , 還 提 供 了 雙 引 號 轉 義 相 關 的 轉 換 。 < / p >
< p > unicode包 提 供 了 IsDigit、 IsLetter、 IsUpper和 IsLower等 類 似 功 能 , 它 們 用 於 給 字 符 分 類 。 每 個 函 數 有 一 個 單 一 的 rune類 型 的 參 數 , 然 後 返 迴 一 個 布 爾 值 。 而 像 ToUpper和 ToLower之 類 的 轉 換 函 數 將 用 於 rune字 符 的 大 小 寫 轉 換 。 所 有 的 這 些 函 數 都 是 遵 循 Unicode標 準 定 義 的 字 母 、 數 字 等 分 類 規 范 。 strings包 也 有 類 似 的 函 數 , 它 們 是 ToUpper和 ToLower, 將 原 始 字 符 串 的 每 個 字 符 都 做 相 應 的 轉 換 , 然 後 返 迴 新 的 字 符 串 。 < / p >
< p > 下 面 例 子 的 basename函 數 靈 感 於 Unix shell的 同 名 工 具 。 在 我 們 實 現 的 版 本 中 , basename(s)將 看 起 來 像 是 繫 統 路 徑 的 前 綴 刪 除 , 同 時 將 看 似 文 件 類 型 的 後 綴 名 部 分 刪 除 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(basename(< span class = "hljs-string" > " a/b/c.go" < / span > )) < span class = "hljs-comment" > // " c" < / span >
fmt.Println(basename(< span class = "hljs-string" > " c.d.go" < / span > )) < span class = "hljs-comment" > // " c.d" < / span >
fmt.Println(basename(< span class = "hljs-string" > " abc" < / span > )) < span class = "hljs-comment" > // " abc" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 第 一 個 版 本 併 沒 有 使 用 任 何 庫 , 全 部 手 工 硬 編 碼 實 現 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > gopl.io/ch3/basename1
< span class = "hljs-comment" > // basename removes directory components and a .suffix.< / span >
< span class = "hljs-comment" > // e.g., a => a, a.go => a, a/b/c.go => c, a/b.c.go => b.c< / span >
< span class = "hljs-keyword" > func< / span > basename(s < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > string< / span > {
< span class = "hljs-comment" > // Discard last ' /' and everything before.< / span >
< span class = "hljs-keyword" > for< / span > i := < span class = "hljs-built_in" > len< / span > (s) - < span class = "hljs-number" > 1< / span > ; i > = < span class = "hljs-number" > 0< / span > ; i-- {
< span class = "hljs-keyword" > if< / span > s[i] == < span class = "hljs-string" > ' /' < / span > {
s = s[i+< span class = "hljs-number" > 1< / span > :]
< span class = "hljs-keyword" > break< / span >
}
}
< span class = "hljs-comment" > // Preserve everything before last ' .' .< / span >
< span class = "hljs-keyword" > for< / span > i := < span class = "hljs-built_in" > len< / span > (s) - < span class = "hljs-number" > 1< / span > ; i > = < span class = "hljs-number" > 0< / span > ; i-- {
< span class = "hljs-keyword" > if< / span > s[i] == < span class = "hljs-string" > ' .' < / span > {
s = s[:i]
< span class = "hljs-keyword" > break< / span >
}
}
< span class = "hljs-keyword" > return< / span > s
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 簡 化 個 版 本 使 用 了 strings.LastIndex庫 函 數 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > gopl.io/ch3/basename2
< span class = "hljs-keyword" > func< / span > basename(s < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > string< / span > {
slash := strings.LastIndex(s, < span class = "hljs-string" > " /" < / span > ) < span class = "hljs-comment" > // -1 if " /" not found< / span >
s = s[slash+< span class = "hljs-number" > 1< / span > :]
< span class = "hljs-keyword" > if< / span > dot := strings.LastIndex(s, < span class = "hljs-string" > " ." < / span > ); dot > = < span class = "hljs-number" > 0< / span > {
s = s[:dot]
}
< span class = "hljs-keyword" > return< / span > s
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > path和 path/filepath包 提 供 了 關 於 文 件 路 徑 名 更 一 般 的 函 數 操 作 。 使 用 斜 槓 分 隔 路 徑 可 以 在 任 何 操 作 繫 統 上 工 作 。 斜 槓 本 身 不 應 該 用 於 文 件 名 , 但 是 在 其 他 一 些 領 域 可 能 會 用 於 文 件 名 , 例 如 URL路 徑 組 件 。 相 比 之 下 , path/filepath包 則 使 用 操 作 繫 統 本 身 的 路 徑 規 則 , 例 如 POSIX繫 統 使 用 /foo/bar, 而 Microsoft Windows使 用 c:\foo\bar等 。 < / p >
< p > 讓 我 們 繼 續 另 一 個 字 符 串 的 例 子 。 函 數 的 功 能 是 將 一 個 表 示 整 值 的 字 符 串 , 每 隔 三 個 字 符 插 入 一 個 逗 號 分 隔 符 , 例 如 “ 12345” 處 理 後 成 爲 “ 12,345” 。 這 個 版 本 隻 適 用 於 整 數 類 型 ; 支 持 浮 點 數 類 型 的 支 持 留 作 練 習 。 < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > gopl.io/ch3/comma
< span class = "hljs-comment" > // comma inserts commas in a non-negative decimal integer string.< / span >
< span class = "hljs-keyword" > func< / span > comma(s < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > string< / span > {
n := < span class = "hljs-built_in" > len< / span > (s)
< span class = "hljs-keyword" > if< / span > n < = < span class = "hljs-number" > 3< / span > {
< span class = "hljs-keyword" > return< / span > s
}
< span class = "hljs-keyword" > return< / span > comma(s[:n-< span class = "hljs-number" > 3< / span > ]) + < span class = "hljs-string" > " ," < / span > + s[n-< span class = "hljs-number" > 3< / span > :]
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 輸 入 comma函 數 的 參 數 是 一 個 字 符 串 。 如 果 輸 入 字 符 串 的 長 度 小 於 或 等 於 3的 話 , 則 不 需 要 插 入 逗 分 隔 符 。 否 則 , comma函 數 將 在 最 後 三 個 字 符 前 位 置 將 字 符 串 切 割 爲 兩 個 兩 個 子 串 併 插 入 逗 號 分 隔 符 , 然 後 通 過 遞 歸 調 用 自 身 來 出 前 面 的 子 串 。 < / p >
< p > 一 個 字 符 串 是 包 含 的 隻 讀 字 節 數 組 , 一 旦 創 建 , 是 不 可 變 的 。 相 比 之 下 , 一 個 字 節 slice的 元 素 則 可 以 自 由 地 脩 改 。 < / p >
< p > 字 符 串 和 字 節 slice之 間 可 以 相 互 轉 換 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > s := < span class = "hljs-string" > " abc" < / span >
b := []< span class = "hljs-typename" > byte< / span > (s)
s2 := < span class = "hljs-typename" > string< / span > (b)
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 從 概 念 上 講 , 一 個 []byte(s)轉 換 是 分 配 了 一 個 新 的 字 節 數 組 用 於 保 存 字 符 串 數 據 的 拷 貝 , 然 後 引 用 這 個 底 層 的 字 節 數 組 。 編 譯 器 的 優 化 可 以 避 免 在 一 些 場 景 下 分 配 和 複 製 字 符 串 數 據 , 但 總 的 來 説 需 要 確 保 在 變 量 b被 脩 改 的 情 況 下 , 原 始 的 s字 符 串 也 不 會 改 變 。 將 一 個 字 節 slice轉 到 字 符 串 的 string(b)操 作 則 是 構 造 一 個 字 符 串 拷 貝 , 以 確 保 s2字 符 串 是 隻 讀 的 。 < / p >
< p > 爲 了 避 免 轉 換 中 不 必 要 的 內 存 分 配 , bytes包 和 strings同 時 提 供 了 許 多 實 用 函 數 。 下 面 是 strings包 中 的 六 個 函 數 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > Contains(s, substr < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > bool< / span >
< span class = "hljs-keyword" > func< / span > Count(s, sep < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > int< / span >
< span class = "hljs-keyword" > func< / span > Fields(s < span class = "hljs-typename" > string< / span > ) []< span class = "hljs-typename" > string< / span >
< span class = "hljs-keyword" > func< / span > HasPrefix(s, prefix < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > bool< / span >
< span class = "hljs-keyword" > func< / span > Index(s, sep < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > int< / span >
< span class = "hljs-keyword" > func< / span > Join(a []< span class = "hljs-typename" > string< / span > , sep < span class = "hljs-typename" > string< / span > ) < span class = "hljs-typename" > string< / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > bytes包 中 也 對 應 的 六 個 函 數 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > Contains(b, subslice []< span class = "hljs-typename" > byte< / span > ) < span class = "hljs-typename" > bool< / span >
< span class = "hljs-keyword" > func< / span > Count(s, sep []< span class = "hljs-typename" > byte< / span > ) < span class = "hljs-typename" > int< / span >
< span class = "hljs-keyword" > func< / span > Fields(s []< span class = "hljs-typename" > byte< / span > ) [][]< span class = "hljs-typename" > byte< / span >
< span class = "hljs-keyword" > func< / span > HasPrefix(s, prefix []< span class = "hljs-typename" > byte< / span > ) < span class = "hljs-typename" > bool< / span >
< span class = "hljs-keyword" > func< / span > Index(s, sep []< span class = "hljs-typename" > byte< / span > ) < span class = "hljs-typename" > int< / span >
< span class = "hljs-keyword" > func< / span > Join(s [][]< span class = "hljs-typename" > byte< / span > , sep []< span class = "hljs-typename" > byte< / span > ) []< span class = "hljs-typename" > byte< / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 它 們 之 間 唯 一 的 區 别 是 字 符 串 類 型 參 數 被 替 換 成 了 字 節 slice類 型 的 參 數 。 < / p >
< p > bytes包 還 提 供 了 Buffer類 型 用 於 字 節 slice的 緩 存 。 一 個 Buffer開 始 是 空 的 , 但 是 隨 着 string、 byte或 []byte等 類 型 數 據 的 寫 入 可 以 動 態 增 長 , 一 個 bytes.Buffer變 量 併 不 需 要 處 理 化 , 因 爲 零 值 也 是 有 效 的 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > gopl.io/ch3/printints
< span class = "hljs-comment" > // intsToString is like fmt.Sprintf(values) but adds commas.< / span >
< span class = "hljs-keyword" > func< / span > intsToString(values []< span class = "hljs-typename" > int< / span > ) < span class = "hljs-typename" > string< / span > {
< span class = "hljs-keyword" > var< / span > buf bytes.Buffer
buf.WriteByte(< span class = "hljs-string" > ' [' < / span > )
< span class = "hljs-keyword" > for< / span > i, v := < span class = "hljs-keyword" > range< / span > values {
< span class = "hljs-keyword" > if< / span > i > < span class = "hljs-number" > 0< / span > {
buf.WriteString(< span class = "hljs-string" > " , " < / span > )
}
fmt.Fprintf(& buf, < span class = "hljs-string" > " %d" < / span > , v)
}
buf.WriteByte(< span class = "hljs-string" > ' ]' < / span > )
< span class = "hljs-keyword" > return< / span > buf.String()
}
< span class = "hljs-keyword" > func< / span > main() {
fmt.Println(intsToString([]< span class = "hljs-typename" > int< / span > {< span class = "hljs-number" > 1< / span > , < span class = "hljs-number" > 2< / span > , < span class = "hljs-number" > 3< / span > })) < span class = "hljs-comment" > // " [1, 2, 3]" < / span >
}
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 當 向 bytes.Buffer添 加 任 意 字 符 的 UTF8編 碼 時 , 最 好 使 用 bytes.Buffer的 WriteRune方 法 , 但 是 WriteByte方 法 對 於 寫 入 類 似 ' [' 和 ' ]' 等 ASCII字 符 則 會 更 加 有 效 。 < / p >
< p > bytes.Buffer類 型 有 着 很 多 實 用 的 功 能 , 我 們 在 第 七 章 討 論 接 口 時 將 會 涉 及 到 , 我 們 將 看 看 如 何 將 它 用 作 一 個 I/O的 輸 入 和 輸 出 對 象 , 例 如 當 做 Fprintf的 io.Writer輸 出 對 象 , 或 者 當 作 io.Reader類 型 的 輸 入 源 對 象 。 < / p >
< p > < strong > 練 習 3.10: < / strong > 編 寫 一 個 非 遞 歸 版 本 的 comma函 數 , 使 用 bytes.Buffer代 替 字 符 串 鏈 接 操 作 。 < / p >
< p > < strong > 練 習 3.11: < / strong > 完 善 comma函 數 , 以 支 持 浮 點 數 處 理 和 一 個 可 選 的 正 負 號 的 處 理 。 < / p >
< p > < strong > 練 習 3.12: < / strong > 編 寫 一 個 函 數 , 判 斷 兩 個 字 符 串 是 否 是 是 相 互 打 亂 的 , 也 就 是 説 它 們 有 着 相 同 的 字 符 , 但 是 對 應 不 同 的 順 序 。 < / p >
2015-12-21 04:55:18 +00:00
< h3 id = "355-字符串和數字的轉換" > 3.5.5. 字 符 串 和 數 字 的 轉 換 < / h3 >
2015-12-28 08:08:26 +00:00
< p > 除 了 字 符 串 、 字 符 、 字 節 之 間 的 轉 換 , 字 符 串 和 數 值 之 間 的 轉 換 也 比 較 常 見 。 由 strconv包 提 供 這 類 轉 換 功 能 。 < / p >
< p > 將 一 個 整 數 轉 爲 字 符 串 , 一 種 方 法 是 用 fmt.Sprintf返 迴 一 個 格 式 化 的 字 符 串 ; 另 一 個 方 法 是 用 strconv.Itoa(“ 整 數 到 ASCII” ): < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > x := < span class = "hljs-number" > 123< / span >
y := fmt.Sprintf(< span class = "hljs-string" > " %d" < / span > , x)
fmt.Println(y, strconv.Itoa(x)) < span class = "hljs-comment" > // " 123 123" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > FormatInt和 FormatUint函 數 可 以 用 不 同 的 進 製 來 格 式 化 數 字 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > fmt.Println(strconv.FormatInt(< span class = "hljs-typename" > int64< / span > (x), < span class = "hljs-number" > 2< / span > )) < span class = "hljs-comment" > // " 1111011" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > fmt.Printf函 數 的 %b、 %d、 %u和 %x等 參 數 提 供 功 能 往 往 比 strconv包 的 Format函 數 方 便 很 多 , 特 别 是 在 需 要 包 含 附 加 額 外 信 息 的 時 候 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > s := fmt.Sprintf(< span class = "hljs-string" > " x=%b" < / span > , x) < span class = "hljs-comment" > // " x=1111011" < / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > 如 果 要 將 一 個 字 符 串 解 析 爲 整 數 , 可 以 使 用 strconv包 的 Atoi或 ParseInt函 數 , 還 有 用 於 解 析 無 符 號 整 數 的 ParseUint函 數 : < / p >
2015-12-21 04:55:18 +00:00
< pre > < code class = "lang-Go" > x, err := strconv.Atoi(< span class = "hljs-string" > " 123" < / span > ) < span class = "hljs-comment" > // x is an int< / span >
y, err := strconv.ParseInt(< span class = "hljs-string" > " 123" < / span > , < span class = "hljs-number" > 10< / span > , < span class = "hljs-number" > 64< / span > ) < span class = "hljs-comment" > // base 10, up to 64 bits< / span >
< / code > < / pre >
2015-12-28 08:08:26 +00:00
< p > ParseInt函 數 的 第 三 個 參 數 是 用 於 指 定 整 型 數 的 大 小 ; 例 如 16表 示 int16, 0則 表 示 int。 在 任 何 情 況 下 , 返 迴 的 結 果 y總 是 int64類 型 , 你 可 以 通 過 強 製 類 型 轉 換 將 它 轉 爲 更 小 的 整 數 類 型 。 < / p >
< p > 有 時 候 也 會 使 用 fmt.Scanf來 解 析 輸 入 的 字 符 串 和 數 字 , 特 别 是 當 字 符 串 和 數 字 混 合 在 一 行 的 時 候 , 它 可 以 靈 活 處 理 不 完 整 或 不 規 則 的 輸 入 。 < / p >
2015-12-09 07:57:17 +00:00
< / section >
< / div >
< / div >
< / div >
2015-12-21 04:55:18 +00:00
< a href = "../ch3/ch3-04.html" class = "navigation navigation-prev " aria-label = "Previous page: 布爾型" > < i class = "fa fa-angle-left" > < / i > < / a >
2015-12-09 07:57:17 +00:00
< a href = "../ch3/ch3-06.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 >