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 > Slice | 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 = "../ch4/ch4-03.html" / >
< link rel = "prev" href = "../ch4/ch4-01.html" / >
< / head >
< body >
2016-01-02 08:04:45 +00:00
< div class = "book"
data-level="4.2"
data-chapter-title="Slice"
data-filepath="ch4/ch4-02.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 " 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 active" 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-" >
2015-12-31 08:20:27 +00:00
< h2 id = "42-slice" > 4.2. Slice< / h2 >
< p > Slice( 切 片 ) 代 表 變 長 的 序 列 , 序 列 中 每 個 元 素 都 有 相 同 的 類 型 。 一 個 slice類 型 一 般 寫 作 []T, 其 中 T代 表 slice中 元 素 的 類 型 ; 語 法 和 數 組 很 像 隻 是 沒 有 長 度 而 已 。 < / p >
< p > 數 組 和 slice之 間 有 着 緊 密 的 聯 繫 。 一 個 slice是 一 個 輕 量 級 的 數 據 結 果 , 提 供 了 訪 問 數 組 子 序 列 ( 或 者 全 部 ) 元 素 的 功 能 , 因 爲 slice的 底 層 確 實 引 用 一 個 數 組 對 象 。 一 個 slice有 三 個 部 分 構 成 : 指 針 、 長 度 和 容 量 。 指 針 指 向 第 一 個 元 素 對 應 的 底 層 數 組 元 素 的 地 址 , slice的 第 一 個 元 素 併 不 一 定 就 是 數 組 的 第 一 個 元 素 。 長 度 對 應 slice中 元 素 的 數 目 ; 長 度 不 能 超 過 容 量 , 容 量 一 般 是 從 slice的 開 始 位 置 到 底 層 數 據 的 結 尾 位 置 。 內 置 的 len和 cap函 數 分 别 返 迴 slice的 長 度 和 容 量 。 < / p >
< p > 多 個 slice之 間 可 以 共 享 底 層 的 數 據 , 併 且 引 用 的 數 組 部 分 區 間 可 能 重 疊 。 圖 4.1顯 示 了 表 示 一 年 中 每 個 月 份 名 字 的 字 符 串 數 組 , 還 有 重 疊 引 用 了 該 數 組 的 兩 個 slice。 數 組 這 樣 定 義 < / p >
< pre > < code class = "lang-Go" > months := [...]< span class = "hljs-typename" > string< / span > {< span class = "hljs-number" > 1< / span > : < span class = "hljs-string" > " January" < / span > , < span class = "hljs-comment" > /* ... */< / span > , < span class = "hljs-number" > 12< / span > : < span class = "hljs-string" > " December" < / span > }
< / code > < / pre >
< p > 因 此 一 月 份 是 months[1], 十 二 月 份 是 months[12]。 通 常 , 數 組 的 第 一 個 元 素 從 索 引 0開 始 , 但 是 月 份 一 般 是 從 1開 始 的 , 因 此 我 們 聲 明 數 組 時 直 接 第 0個 元 素 , 第 0個 元 素 會 被 自 動 初 始 化 爲 空 字 符 串 。 < / p >
< p > slice的 操 作 s[i:j], 其 中 0 ≤ i≤ j≤ cap(s), 用 於 創 建 一 個 新 的 slice, 引 用 s的 從 第 i個 元 素 開 始 到 第 j-1個 元 素 的 子 序 列 。 新 的 slice將 隻 有 j-i個 元 素 。 如 果 i位 置 的 索 引 被 省 略 的 話 將 使 用 0代 替 , 如 果 j位 置 的 索 引 被 省 略 的 話 將 使 用 len(s)代 替 。 因 此 , months[1:13]切 片 操 作 將 引 用 全 部 有 效 的 月 份 , 和 months[1:]操 作 等 價 ; months[:]切 片 操 作 則 是 引 用 整 個 數 組 。 讓 我 們 分 别 定 義 表 示 第 二 季 度 和 北 方 夏 天 的 slice, 它 們 有 重 疊 部 分 : < / p >
< p > < img src = "../images/ch4-01.png" alt = "" > < / p >
< pre > < code class = "lang-Go" > Q2 := months[< span class = "hljs-number" > 4< / span > :< span class = "hljs-number" > 7< / span > ]
summer := months[< span class = "hljs-number" > 6< / span > :< span class = "hljs-number" > 9< / span > ]
fmt.Println(Q2) < span class = "hljs-comment" > // [" April" " May" " June" ]< / span >
fmt.Println(summer) < span class = "hljs-comment" > // [" June" " July" " August" ]< / span >
< / code > < / pre >
< p > 兩 個 slice都 包 含 了 六 月 份 , 下 面 的 代 碼 是 一 個 包 含 相 同 月 份 的 測 試 ( 性 能 較 低 ) : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > for< / span > _, s := < span class = "hljs-keyword" > range< / span > summer {
< span class = "hljs-keyword" > for< / span > _, q := < span class = "hljs-keyword" > range< / span > Q2 {
< span class = "hljs-keyword" > if< / span > s == q {
fmt.Printf(< span class = "hljs-string" > " %s appears in both\n" < / span > , s)
}
}
}
< / code > < / pre >
< p > 如 果 切 片 操 作 長 處 cap(s)的 上 限 將 導 致 一 個 panic異 常 , 但 是 超 出 len(s)則 是 擴 展 了 slice, 因 此 新 slice的 長 度 會 變 大 : < / p >
< pre > < code class = "lang-Go" > fmt.Println(summer[:< span class = "hljs-number" > 20< / span > ]) < span class = "hljs-comment" > // panic: out of range< / span >
endlessSummer := summer[:< span class = "hljs-number" > 5< / span > ] < span class = "hljs-comment" > // extend a slice (within capacity)< / span >
fmt.Println(endlessSummer) < span class = "hljs-comment" > // " [June July August September October]" < / span >
< / code > < / pre >
< p > 另 外 , 字 符 串 的 切 片 操 作 和 []byte字 節 類 型 切 片 的 切 片 操 作 是 類 似 的 。 它 們 都 寫 作 x[m:n], 併 且 都 是 返 迴 一 個 原 始 字 節 繫 列 的 子 序 列 , 底 層 都 是 共 享 之 前 的 底 層 數 組 , 因 此 切 片 操 作 對 應 常 量 時 間 複 雜 度 。 x[m:n]切 片 操 作 對 於 字 符 串 則 生 成 一 個 新 字 符 串 , 如 果 x是 []byte的 話 則 生 成 一 個 新 的 []byte。 < / p >
< p > 因 爲 slice值 包 含 指 向 第 一 個 元 素 的 指 針 , 因 此 向 函 數 傳 遞 slice將 運 行 在 函 數 內 部 脩 改 底 層 數 組 的 元 素 。 換 句 話 説 , 複 雜 一 個 slice隻 是 對 底 層 的 數 組 創 建 了 一 個 新 的 slice别 名 ( § 2.3.2) 。 下 面 的 reverse函 數 在 原 內 存 空 間 將 []int類 型 的 slice反 轉 , 而 且 它 可 以 用 於 任 意 長 度 的 slice。 < / p >
< pre > < code class = "lang-Go" > gopl.io/ch4/rev
< span class = "hljs-comment" > // reverse reverses a slice of ints in place.< / span >
< span class = "hljs-keyword" > func< / span > reverse(s []< span class = "hljs-typename" > int< / span > ) {
< span class = "hljs-keyword" > for< / span > i, j := < span class = "hljs-number" > 0< / span > , < span class = "hljs-built_in" > len< / span > (s)-< span class = "hljs-number" > 1< / span > ; i < j; i, j = i+< span class = "hljs-number" > 1< / span > , j-< span class = "hljs-number" > 1< / span > {
s[i], s[j] = s[j], s[i]
}
}
< / code > < / pre >
< p > 這 里 我 們 反 轉 數 組 的 應 用 : < / p >
< pre > < code class = "lang-Go" > a := [...]< span class = "hljs-typename" > int< / span > {< span class = "hljs-number" > 0< / span > , < span class = "hljs-number" > 1< / span > , < span class = "hljs-number" > 2< / span > , < span class = "hljs-number" > 3< / span > , < span class = "hljs-number" > 4< / span > , < span class = "hljs-number" > 5< / span > }
reverse(a[:])
fmt.Println(a) < span class = "hljs-comment" > // " [5 4 3 2 1 0]" < / span >
< / code > < / pre >
< p > 一 種 將 slice元 素 循 環 向 左 镟 轉 n個 元 素 的 方 法 是 三 次 調 用 reverse反 轉 函 數 , 第 一 次 是 反 轉 開 頭 的 n個 元 素 , 然 後 是 反 轉 剩 下 的 元 素 , 最 後 是 反 轉 整 個 slice的 元 素 。 ( 如 果 是 向 右 循 環 镟 轉 , 則 將 第 三 個 函 數 調 用 移 到 第 一 個 調 用 位 置 就 可 以 了 。 ) < / p >
< pre > < code class = "lang-Go" > s := []< span class = "hljs-typename" > int< / span > {< span class = "hljs-number" > 0< / span > , < span class = "hljs-number" > 1< / span > , < span class = "hljs-number" > 2< / span > , < span class = "hljs-number" > 3< / span > , < span class = "hljs-number" > 4< / span > , < span class = "hljs-number" > 5< / span > }
< span class = "hljs-comment" > // Rotate s left by two positions.< / span >
reverse(s[:< span class = "hljs-number" > 2< / span > ])
reverse(s[< span class = "hljs-number" > 2< / span > :])
reverse(s)
fmt.Println(s) < span class = "hljs-comment" > // " [2 3 4 5 0 1]" < / span >
< / code > < / pre >
< p > 要 註 意 的 是 slice類 型 的 變 量 s和 數 組 類 型 的 變 量 a的 初 始 化 語 法 的 差 異 。 slice和 數 組 的 字 面 值 語 法 很 類 似 , 它 們 都 是 用 花 括 弧 包 含 一 繫 列 的 初 始 化 元 素 , 但 是 對 於 slice併 沒 有 指 明 序 列 的 長 度 。 這 會 隱 式 地 創 建 一 個 合 適 大 小 的 數 組 , 然 後 slice的 指 針 指 向 底 層 的 數 組 。 就 像 數 組 字 面 值 一 樣 , slice的 字 面 值 也 可 以 按 順 序 指 定 初 始 化 值 序 列 , 或 者 是 通 過 索 引 和 元 素 值 指 定 , 或 者 的 兩 種 風 格 的 混 合 語 法 初 始 化 。 < / p >
< p > 和 數 組 不 同 的 是 , slice不 能 比 較 , 因 此 我 們 不 能 使 用 ==操 作 符 來 判 斷 兩 個 slice是 否 有 相 同 的 元 素 。 不 過 標 準 庫 提 供 了 高 度 優 化 的 bytes.Equal函 數 來 判 斷 兩 個 字 節 型 slice是 否 相 等 ( []byte) , 但 是 對 於 其 他 類 型 的 slice, 我 們 必 鬚 自 己 展 開 每 個 元 素 進 行 比 較 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > equal(x, y []< span class = "hljs-typename" > string< / 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 > i := < span class = "hljs-keyword" > range< / span > x {
< span class = "hljs-keyword" > if< / span > x[i] != y[i] {
< 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 > 上 面 關 於 兩 個 slice的 深 度 相 等 測 試 , 運 行 的 時 間 併 不 比 支 持 ==操 作 的 數 組 或 字 符 串 更 多 , 但 是 爲 何 slice卻 不 支 持 比 較 運 算 符 呢 ? 這 方 面 有 兩 個 原 因 。 第 一 個 原 因 , 一 個 slice的 元 素 是 間 接 引 用 的 , 一 個 slice甚 至 可 以 包 含 自 身 。 雖 然 有 很 多 辦 法 處 理 這 種 情 形 , 但 是 沒 有 一 個 是 簡 單 有 效 的 。 < / p >
< p > 第 二 個 原 因 , 因 爲 slice的 元 素 是 間 接 引 用 的 , 一 個 固 定 值 的 slice在 不 同 的 時 間 可 能 包 含 不 同 的 元 素 , 因 爲 底 層 數 組 的 元 素 可 能 會 被 脩 改 。 併 且 Go語 言 中 map等 哈 希 表 之 類 的 數 據 結 構 的 key隻 做 簡 單 的 淺 拷 貝 , 它 要 求 在 整 個 聲 明 週 期 中 相 等 的 key必 鬚 對 相 同 的 元 素 。 對 於 像 指 針 或 chan之 類 的 引 用 類 型 , ==相 等 測 試 可 以 判 斷 兩 個 是 否 是 引 用 相 同 的 對 象 。 一 個 針 對 slice的 淺 相 等 測 試 的 ==操 作 符 可 能 是 有 一 定 用 處 的 , 也 能 臨 時 解 決 map類 型 的 key問 題 , 但 是 slice和 數 組 不 同 的 相 等 測 試 行 爲 會 讓 人 睏 惑 。 因 此 , 安 全 的 做 飯 是 直 接 禁 止 slice之 間 的 比 較 操 作 。 < / p >
< p > slice唯 一 合 法 的 比 較 是 和 nil比 較 , 例 如 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > if< / span > summer == < span class = "hljs-constant" > nil< / span > { < span class = "hljs-comment" > /* ... */< / span > }
< / code > < / pre >
< p > 一 個 零 值 的 slice等 於 nil。 一 個 nil值 的 slice併 沒 有 底 層 數 組 。 一 個 nil值 的 slice的 長 度 和 容 量 都 是 0, 但 是 也 有 非 nil值 的 slice的 長 度 和 容 量 也 是 0的 , 例 如 []int{}或 make([]int, 3)[3:]。 與 任 意 類 型 的 nil值 一 樣 , 我 們 可 以 用 []int(nil)類 型 轉 換 表 達 式 來 生 成 一 個 對 應 類 型 slice的 nil值 。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > var< / span > s []< span class = "hljs-typename" > int< / span > < span class = "hljs-comment" > // len(s) == 0, s == nil< / span >
s = < span class = "hljs-constant" > nil< / span > < span class = "hljs-comment" > // len(s) == 0, s == nil< / span >
s = []< span class = "hljs-typename" > int< / span > (< span class = "hljs-constant" > nil< / span > ) < span class = "hljs-comment" > // len(s) == 0, s == nil< / span >
s = []< span class = "hljs-typename" > int< / span > {} < span class = "hljs-comment" > // len(s) == 0, s != nil< / span >
< / code > < / pre >
< p > 如 果 你 需 要 測 試 一 個 slice是 否 是 空 的 , 使 用 len(s) == 0來 判 斷 , 而 不 是 用 s == nil來 判 斷 。 除 了 和 nil相 等 比 較 外 , 一 個 nil值 的 slice的 行 爲 和 其 它 任 意 0産 長 度 的 slice一 樣 ; 例 如 reverse(nil)也 是 安 全 的 。 除 了 文 檔 已 經 明 確 説 明 的 地 方 , 所 有 的 Go語 言 函 數 應 該 以 相 同 的 方 式 對 待 nil值 的 slice和 0長 度 的 slice。 < / p >
< p > 內 置 的 make函 數 創 建 一 個 指 定 元 素 類 型 、 長 度 和 容 量 的 slice。 容 量 部 分 可 以 省 略 , 在 這 種 情 況 下 , 容 量 將 等 於 長 度 。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-built_in" > make< / span > ([]T, < span class = "hljs-built_in" > len< / span > )
< span class = "hljs-built_in" > make< / span > ([]T, < span class = "hljs-built_in" > len< / span > , < span class = "hljs-built_in" > cap< / span > ) < span class = "hljs-comment" > // same as make([]T, cap)[:len]< / span >
< / code > < / pre >
< p > 在 底 層 , make創 建 了 一 個 匿 名 的 數 組 變 量 , 然 後 返 迴 一 個 slice; 隻 有 通 過 返 迴 的 slice才 能 引 用 底 層 匿 名 的 數 組 變 量 。 在 第 一 種 語 句 中 , slice是 整 個 數 組 的 view。 在 第 二 個 語 句 中 , slice隻 引 用 了 底 層 數 組 的 前 len個 元 素 , 但 是 容 量 將 包 含 整 個 的 數 組 。 額 外 的 元 素 是 留 給 未 來 的 增 長 用 的 。 < / p >
2015-12-28 08:08:26 +00:00
< h3 id = "421-append函數" > 4.2.1. append函 數 < / h3 >
2015-12-31 08:20:27 +00:00
< p > 內 置 的 append函 數 用 於 向 slice追 加 元 素 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > var< / span > runes []< span class = "hljs-typename" > rune< / span >
< span class = "hljs-keyword" > for< / span > _, r := < span class = "hljs-keyword" > range< / span > < span class = "hljs-string" > " Hello, 世 界 " < / span > {
runes = < span class = "hljs-built_in" > append< / span > (runes, r)
}
fmt.Printf(< span class = "hljs-string" > " %q\n" < / span > , runes) < span class = "hljs-comment" > // " [' H' ' e' ' l' ' l' ' o' ' ,' ' ' ' 世 ' ' 界 ' ]" < / span >
< / code > < / pre >
< p > 在 循 環 中 使 用 append函 數 構 建 一 個 有 九 個 rune字 符 構 成 的 slice, 當 然 對 應 這 個 特 殊 的 問 題 我 們 可 以 通 過 Go語 言 內 置 的 []rune(" Hello, 世 界 " )轉 換 操 作 完 成 。 < / p >
< p > append函 數 對 於 理 解 slice底 層 是 如 何 工 作 的 非 常 重 要 , 所 以 讓 我 們 仔 細 査 看 究 竟 是 發 生 了 什 麽 。 下 面 是 第 一 個 版 本 的 appendInt函 數 , 專 門 用 於 處 理 []int類 型 的 slice: < / p >
< pre > < code class = "lang-Go" > gopl.io/ch4/< span class = "hljs-built_in" > append< / span >
< span class = "hljs-keyword" > func< / span > appendInt(x []< span class = "hljs-typename" > int< / span > , y < span class = "hljs-typename" > int< / span > ) []< span class = "hljs-typename" > int< / span > {
< span class = "hljs-keyword" > var< / span > z []< span class = "hljs-typename" > int< / span >
zlen := < span class = "hljs-built_in" > len< / span > (x) + < span class = "hljs-number" > 1< / span >
< span class = "hljs-keyword" > if< / span > zlen < = < span class = "hljs-built_in" > cap< / span > (x) {
< span class = "hljs-comment" > // There is room to grow. Extend the slice.< / span >
z = x[:zlen]
} < span class = "hljs-keyword" > else< / span > {
< span class = "hljs-comment" > // There is insufficient space. Allocate a new array.< / span >
< span class = "hljs-comment" > // Grow by doubling, for amortized linear complexity.< / span >
zcap := zlen
< span class = "hljs-keyword" > if< / span > zcap < < span class = "hljs-number" > 2< / span > *< span class = "hljs-built_in" > len< / span > (x) {
zcap = < span class = "hljs-number" > 2< / span > * < span class = "hljs-built_in" > len< / span > (x)
}
z = < span class = "hljs-built_in" > make< / span > ([]< span class = "hljs-typename" > int< / span > , zlen, zcap)
< span class = "hljs-built_in" > copy< / span > (z, x) < span class = "hljs-comment" > // a built-in function; see text< / span >
}
z[< span class = "hljs-built_in" > len< / span > (x)] = y
< span class = "hljs-keyword" > return< / span > z
}
< / code > < / pre >
< p > 每 次 調 用 appendInt函 數 , 必 鬚 先 檢 測 slice底 層 數 組 是 否 有 足 夠 的 容 量 來 保 存 新 添 加 的 元 素 。 如 果 有 足 夠 空 間 的 話 , 直 接 擴 展 slice( 依 然 在 原 有 的 底 層 數 組 之 上 ) , 將 新 添 加 的 y元 素 複 製 到 新 擴 展 的 空 間 , 併 返 迴 slice。 因 此 , 輸 入 的 x和 輸 出 的 z共 享 相 同 的 底 層 數 組 。 < / p >
< p > 如 果 沒 有 足 夠 的 增 長 空 間 的 話 , appendInt函 數 則 會 先 分 配 一 個 足 夠 大 的 slice用 於 保 存 新 的 結 果 , 先 將 輸 入 的 x複 製 到 新 的 空 間 , 然 後 添 加 y元 素 。 結 果 z和 輸 入 的 x引 用 的 將 是 不 同 的 底 層 數 組 。 < / p >
< p > 雖 然 通 過 循 環 複 製 元 素 更 直 接 , 不 過 內 置 的 copy函 數 可 以 方 便 地 將 一 個 slice複 製 另 一 個 相 同 類 型 的 slice。 copy函 數 的 第 一 個 參 數 是 要 複 製 的 目 標 slice, 第 二 個 參 數 是 源 slice, 目 標 和 源 的 位 置 順 序 和 dst = src賦 值 語 句 是 一 致 的 。 兩 個 slice可 以 共 享 同 一 個 底 層 數 組 , 甚 至 有 重 疊 也 沒 有 問 題 。 copy函 數 將 返 迴 成 功 複 製 的 元 素 的 個 數 ( 我 們 這 里 沒 有 用 到 ) , 等 於 兩 個 slice中 較 小 的 長 度 , 所 以 我 們 不 用 擔 心 覆 蓋 會 超 出 目 的 slice的 范 圍 。 < / p >
< p > 爲 了 效 率 , 新 分 配 的 數 組 一 般 略 大 於 保 存 x和 y所 需 要 的 最 低 大 小 。 通 過 在 每 次 擴 展 數 組 時 直 接 將 長 度 翻 倍 從 而 避 免 了 多 次 內 存 分 配 , 也 確 保 了 添 加 單 個 元 素 操 的 平 均 時 間 是 一 個 常 數 時 間 。 這 個 程 序 演 示 了 效 果 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > main() {
< span class = "hljs-keyword" > var< / span > x, y []< span class = "hljs-typename" > int< / span >
< span class = "hljs-keyword" > for< / span > i := < span class = "hljs-number" > 0< / span > ; i < < span class = "hljs-number" > 10< / span > ; i++ {
y = appendInt(x, i)
fmt.Printf(< span class = "hljs-string" > " %d cap=%d\t%v\n" < / span > , i, < span class = "hljs-built_in" > cap< / span > (y), y)
x = y
}
}
< / code > < / pre >
< p > 每 一 次 容 量 的 變 化 都 會 導 致 重 新 分 配 內 存 和 copy操 作 : < / p >
< pre > < code > 0 cap=1 [0]
1 cap=2 [0 1]
2 cap=4 [0 1 2]
3 cap=4 [0 1 2 3]
4 cap=8 [0 1 2 3 4]
5 cap=8 [0 1 2 3 4 5]
6 cap=8 [0 1 2 3 4 5 6]
7 cap=8 [0 1 2 3 4 5 6 7]
8 cap=16 [0 1 2 3 4 5 6 7 8]
9 cap=16 [0 1 2 3 4 5 6 7 8 9]
< / code > < / pre > < p > 讓 我 們 仔 細 査 看 i=3次 的 迭 代 。 當 時 x包 含 了 [0 1 2]三 個 元 素 , 但 是 容 量 是 4, 因 此 可 以 簡 單 將 新 的 元 素 添 加 到 末 尾 , 不 需 要 新 的 內 存 分 配 。 然 後 新 的 y的 長 度 和 容 量 都 是 4, 併 且 和 x引 用 着 相 同 的 底 層 數 組 , 如 圖 4.2所 示 。 < / p >
< p > < img src = "../images/ch4-02.png" alt = "" > < / p >
< p > 在 下 一 次 迭 代 時 i=4, 現 在 沒 有 新 的 空 餘 的 空 間 了 , 因 此 appendInt函 數 分 配 一 個 容 量 爲 8的 底 層 數 組 , 將 x的 4個 元 素 [0 1 2 3]複 製 到 新 空 間 的 開 頭 , 然 後 添 加 新 的 元 素 i, 新 元 素 的 值 是 4。 新 的 y的 長 度 是 5, 容 量 是 8; 後 面 有 3個 空 閒 的 位 置 , 三 次 迭 代 都 不 需 要 分 配 新 的 空 間 。 當 前 迭 代 中 , y和 x是 對 應 不 用 底 層 數 組 的 view。 這 次 操 作 如 圖 4.3所 示 。 < / p >
< p > < img src = "../images/ch4-03.png" alt = "" > < / p >
< p > 內 置 的 append函 數 可 能 使 用 比 appendInt更 複 雜 的 內 存 擴 展 策 略 。 因 此 , 通 常 我 們 併 不 知 道 append調 用 是 否 導 致 了 內 存 的 分 配 , 因 此 我 們 也 不 能 確 認 新 的 slice和 原 始 的 slice是 否 引 用 的 是 相 同 的 底 層 數 組 空 間 。 同 樣 , 我 們 不 能 確 認 在 原 先 的 slice上 的 操 作 是 否 會 影 響 到 新 的 slice。 因 此 , 通 常 是 將 append返 迴 的 結 果 直 接 賦 值 給 輸 入 的 slice變 量 : < / p >
< pre > < code class = "lang-Go" > runes = < span class = "hljs-built_in" > append< / span > (runes, r)
< / code > < / pre >
< p > 更 新 slice變 量 不 僅 對 調 用 append函 數 是 必 要 的 , 實 際 上 對 應 任 何 可 能 導 致 長 度 、 容 量 或 底 層 數 組 變 化 的 操 作 都 是 必 要 的 。 要 正 確 地 使 用 slice, 需 要 記 住 盡 管 底 層 數 組 的 元 素 是 間 接 訪 問 , 但 是 slice本 身 的 指 針 、 長 度 和 容 量 是 直 接 訪 問 的 。 要 更 新 這 些 信 息 需 要 像 上 面 例 子 那 樣 一 個 顯 式 的 賦 值 操 作 。 從 這 個 角 度 看 , slice併 不 是 一 個 純 粹 的 引 用 類 型 , 它 實 際 上 是 一 個 類 似 下 面 結 構 體 的 聚 合 類 型 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > type< / span > IntSlice < span class = "hljs-keyword" > struct< / span > {
ptr *< span class = "hljs-typename" > int< / span >
< span class = "hljs-built_in" > len< / span > , < span class = "hljs-built_in" > cap< / span > < span class = "hljs-typename" > int< / span >
}
< / code > < / pre >
< p > 我 們 的 appendInt函 數 每 次 隻 能 向 slice追 加 一 個 元 素 , 但 是 內 置 的 append函 數 則 可 以 追 加 多 個 元 素 , 甚 至 追 加 一 個 slice。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > var< / span > x []< span class = "hljs-typename" > int< / span >
x = < span class = "hljs-built_in" > append< / span > (x, < span class = "hljs-number" > 1< / span > )
x = < span class = "hljs-built_in" > append< / span > (x, < span class = "hljs-number" > 2< / span > , < span class = "hljs-number" > 3< / span > )
x = < span class = "hljs-built_in" > append< / span > (x, < span class = "hljs-number" > 4< / span > , < span class = "hljs-number" > 5< / span > , < span class = "hljs-number" > 6< / span > )
x = < span class = "hljs-built_in" > append< / span > (x, x...) < span class = "hljs-comment" > // append the slice x< / span >
fmt.Println(x) < span class = "hljs-comment" > // " [1 2 3 4 5 6 1 2 3 4 5 6]" < / span >
< / code > < / pre >
< p > 通 過 下 面 的 小 脩 改 , 我 們 可 以 可 以 達 到 append函 數 類 似 的 功 能 。 其 中 在 appendInt函 數 參 數 中 的 最 後 的 “ ...” 省 略 號 表 示 接 收 變 長 的 參 數 爲 slice。 我 們 將 在 5.7節 詳 細 解 釋 這 個 特 性 。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > appendInt(x []< span class = "hljs-typename" > int< / span > , y ...< span class = "hljs-typename" > int< / span > ) []< span class = "hljs-typename" > int< / span > {
< span class = "hljs-keyword" > var< / span > z []< span class = "hljs-typename" > int< / span >
zlen := < span class = "hljs-built_in" > len< / span > (x) + < span class = "hljs-built_in" > len< / span > (y)
< span class = "hljs-comment" > // ...expand z to at least zlen...< / span >
< span class = "hljs-built_in" > copy< / span > (z[< span class = "hljs-built_in" > len< / span > (x):], y)
< span class = "hljs-keyword" > return< / span > z
}
< / code > < / pre >
< p > 爲 了 避 免 重 複 , 和 前 面 相 同 的 代 碼 併 沒 有 顯 示 。 < / p >
2015-12-28 08:08:26 +00:00
< h3 id = "422-slice內存技巧" > 4.2.2. Slice內 存 技 巧 < / h3 >
2015-12-31 08:20:27 +00:00
< p > 讓 我 們 看 看 更 多 的 例 子 , 比 如 镟 轉 slice、 反 轉 slice或 在 slice原 有 內 存 空 間 脩 改 元 素 。 給 定 一 個 字 符 串 列 表 , 下 面 的 nonempty函 數 將 在 原 有 slice內 存 空 間 之 上 返 迴 不 包 含 空 字 符 串 的 列 表 : < / p >
< pre > < code class = "lang-Go" > gopl.io/ch4/nonempty
< span class = "hljs-comment" > // Nonempty is an example of an in-place slice algorithm.< / span >
< span class = "hljs-keyword" > package< / span > main
< span class = "hljs-keyword" > import< / span > < span class = "hljs-string" > " fmt" < / span >
< span class = "hljs-comment" > // nonempty returns a slice holding only the non-empty strings.< / span >
< span class = "hljs-comment" > // The underlying array is modified during the call.< / span >
< span class = "hljs-keyword" > func< / span > nonempty(strings []< span class = "hljs-typename" > string< / span > ) []< span class = "hljs-typename" > string< / span > {
i := < span class = "hljs-number" > 0< / span >
< span class = "hljs-keyword" > for< / span > _, s := < span class = "hljs-keyword" > range< / span > strings {
< span class = "hljs-keyword" > if< / span > s != < span class = "hljs-string" > " " < / span > {
strings[i] = s
i++
}
}
< span class = "hljs-keyword" > return< / span > strings[:i]
}
< / code > < / pre >
< p > 比 較 微 妙 的 地 方 是 , 輸 入 的 slice和 輸 出 的 slice共 享 一 個 底 層 數 組 。 這 可 以 避 免 分 配 另 一 個 數 組 , 不 過 原 來 的 數 據 將 可 能 會 被 覆 蓋 , 正 如 下 面 兩 個 打 印 語 句 看 到 的 那 樣 : < / p >
< pre > < code class = "lang-Go" > data := []< span class = "hljs-typename" > string< / span > {< span class = "hljs-string" > " one" < / span > , < span class = "hljs-string" > " " < / span > , < span class = "hljs-string" > " three" < / span > }
fmt.Printf(< span class = "hljs-string" > " %q\n" < / span > , nonempty(data)) < span class = "hljs-comment" > // `[" one" " three" ]`< / span >
fmt.Printf(< span class = "hljs-string" > " %q\n" < / span > , data) < span class = "hljs-comment" > // `[" one" " three" " three" ]`< / span >
< / code > < / pre >
< p > 因 此 我 們 通 常 會 這 樣 使 用 nonempty函 數 : data = nonempty(data)。 < / p >
< p > nonempty函 數 也 可 以 使 用 append函 數 實 現 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > nonempty2(strings []< span class = "hljs-typename" > string< / span > ) []< span class = "hljs-typename" > string< / span > {
out := strings[:< span class = "hljs-number" > 0< / span > ] < span class = "hljs-comment" > // zero-length slice of original< / span >
< span class = "hljs-keyword" > for< / span > _, s := < span class = "hljs-keyword" > range< / span > strings {
< span class = "hljs-keyword" > if< / span > s != < span class = "hljs-string" > " " < / span > {
out = < span class = "hljs-built_in" > append< / span > (out, s)
}
}
< span class = "hljs-keyword" > return< / span > out
}
< / code > < / pre >
< p > 無 論 如 何 實 現 , 以 這 種 方 式 重 用 一 個 slice一 般 要 求 最 多 爲 每 個 輸 入 值 産 生 一 個 輸 出 值 , 事 實 上 很 多 算 法 都 是 用 來 過 濾 或 合 併 序 列 中 相 鄰 的 元 素 。 這 種 slice用 法 是 比 較 複 雜 的 技 巧 , 雖 然 使 用 到 了 slice的 一 些 黑 魔 法 , 但 是 對 於 某 些 場 合 是 比 較 清 晰 和 有 效 的 。 < / p >
< p > 一 個 slice可 以 原 來 實 現 一 個 stack。 最 初 給 定 的 空 slice對 應 一 個 空 的 stack, 然 後 可 以 使 用 append函 數 將 新 的 值 壓 入 stack: < / p >
< pre > < code class = "lang-Go" > stack = < span class = "hljs-built_in" > append< / span > (stack, v) < span class = "hljs-comment" > // push v< / span >
< / code > < / pre >
< p > stack的 頂 部 位 置 對 應 slice的 最 後 一 個 元 素 : < / p >
< pre > < code class = "lang-Go" > top := stack[< span class = "hljs-built_in" > len< / span > (stack)-< span class = "hljs-number" > 1< / span > ] < span class = "hljs-comment" > // top of stack< / span >
< / code > < / pre >
< p > 通 過 收 縮 stack可 以 彈 出 棧 頂 的 元 素 < / p >
< pre > < code class = "lang-Go" > stack = stack[:< span class = "hljs-built_in" > len< / span > (stack)-< span class = "hljs-number" > 1< / span > ] < span class = "hljs-comment" > // pop< / span >
< / code > < / pre >
< p > 要 刪 除 slice中 間 的 某 個 元 素 併 保 存 原 有 的 元 素 順 序 , 可 以 通 過 內 置 的 copy函 數 將 後 面 的 子 slice向 前 一 位 複 雜 完 成 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > remove(slice []< span class = "hljs-typename" > int< / span > , i < span class = "hljs-typename" > int< / span > ) []< span class = "hljs-typename" > int< / span > {
< span class = "hljs-built_in" > copy< / span > (slice[i:], slice[i+< span class = "hljs-number" > 1< / span > :])
< span class = "hljs-keyword" > return< / span > slice[:< span class = "hljs-built_in" > len< / span > (slice)-< span class = "hljs-number" > 1< / span > ]
}
< span class = "hljs-keyword" > func< / span > main() {
s := []< span class = "hljs-typename" > int< / span > {< span class = "hljs-number" > 5< / span > , < span class = "hljs-number" > 6< / span > , < span class = "hljs-number" > 7< / span > , < span class = "hljs-number" > 8< / span > , < span class = "hljs-number" > 9< / span > }
fmt.Println(remove(s, < span class = "hljs-number" > 2< / span > )) < span class = "hljs-comment" > // " [5 6 8 9]" < / span >
}
< / code > < / pre >
< p > 如 果 刪 除 元 素 後 不 用 保 存 原 來 順 序 的 話 , 我 們 可 以 簡 單 的 用 最 後 一 個 元 素 覆 蓋 被 刪 除 的 元 素 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > remove(slice []< span class = "hljs-typename" > int< / span > , i < span class = "hljs-typename" > int< / span > ) []< span class = "hljs-typename" > int< / span > {
slice[i] = slice[< span class = "hljs-built_in" > len< / span > (slice)-< span class = "hljs-number" > 1< / span > ]
< span class = "hljs-keyword" > return< / span > slice[:< span class = "hljs-built_in" > len< / span > (slice)-< span class = "hljs-number" > 1< / span > ]
}
< span class = "hljs-keyword" > func< / span > main() {
s := []< span class = "hljs-typename" > int< / span > {< span class = "hljs-number" > 5< / span > , < span class = "hljs-number" > 6< / span > , < span class = "hljs-number" > 7< / span > , < span class = "hljs-number" > 8< / span > , < span class = "hljs-number" > 9< / span > }
fmt.Println(remove(s, < span class = "hljs-number" > 2< / span > )) < span class = "hljs-comment" > // " [5 6 9 8]< / span >
}
< / code > < / pre >
< p > < strong > 練 習 4.3: < / strong > 重 寫 reverse函 數 , 使 用 數 組 指 針 代 替 slice。 < / p >
< p > < strong > 練 習 4.4: < / strong > 編 寫 一 個 rotate函 數 , 通 過 一 次 循 環 完 成 镟 轉 。 < / p >
< p > < strong > 練 習 4.5: < / strong > 寫 一 個 函 數 在 原 地 完 成 消 除 []string中 相 鄰 重 複 的 字 符 串 的 操 作 。 < / p >
< p > < strong > 練 習 4.6: < / strong > 編 寫 一 個 函 數 , 原 地 將 一 個 UTF-8編 碼 的 []byte類 型 的 slice中 相 鄰 的 空 格 ( 參 考 unicode.IsSpace) 替 換 成 一 個 空 格 返 迴 < / p >
< p > < strong > 練 習 4.7: < / strong > 脩 改 reverse函 數 用 於 原 地 反 轉 UTF-8編 碼 的 []byte。 是 否 可 以 不 用 分 配 額 外 的 內 存 ? < / p >
2015-12-09 07:57:17 +00:00
< / section >
< / div >
< / div >
< / div >
< a href = "../ch4/ch4-01.html" class = "navigation navigation-prev " aria-label = "Previous page: 數組" > < i class = "fa fa-angle-left" > < / i > < / a >
2015-12-31 08:20:27 +00:00
< a href = "../ch4/ch4-03.html" class = "navigation navigation-next " aria-label = "Next page: Map" > < i class = "fa fa-angle-right" > < / i > < / a >
2015-12-09 07:57:17 +00:00
< / 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 >