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 > Display遞歸打印 | 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 = "../ch12/ch12-04.html" / >
< link rel = "prev" href = "../ch12/ch12-02.html" / >
< / head >
< body >
2016-01-02 08:04:45 +00:00
< div class = "book"
data-level="12.3"
data-chapter-title="Display遞歸打印"
data-filepath="ch12/ch12-03.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 " 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 active" 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 = "123-display遞歸打印" > 12.3. Display遞 歸 打 印 < / h2 >
2016-01-02 08:04:45 +00:00
< p > 接 下 來 , 讓 我 們 看 看 如 何 改 善 聚 合 數 據 類 型 的 顯 示 。 我 們 併 不 想 完 全 剋 隆 一 個 fmt.Sprint函 數 , 我 們 隻 是 像 構 建 一 個 用 於 調 式 用 的 Display函 數 , 給 定 一 個 聚 合 類 型 x, 打 印 這 個 值 對 應 的 完 整 的 結 構 , 同 時 記 録 每 個 發 現 的 每 個 元 素 的 路 徑 。 讓 我 們 從 一 個 例 子 開 始 。 < / p >
< pre > < code class = "lang-Go" > e, _ := eval.Parse(< span class = "hljs-string" > " sqrt(A / pi)" < / span > )
Display(< span class = "hljs-string" > " e" < / span > , e)
< / code > < / pre >
< p > 在 上 面 的 調 用 中 , 傳 入 Display函 數 的 參 數 是 在 7.9節 一 個 表 達 式 求 值 函 數 返 迴 的 語 法 樹 。 Display函 數 的 輸 出 如 下 : < / p >
< pre > < code class = "lang-Go" > Display e (eval.call):
e.fn = < span class = "hljs-string" > " sqrt" < / span >
e.args[< span class = "hljs-number" > 0< / span > ].< span class = "hljs-keyword" > type< / span > = eval.binary
e.args[< span class = "hljs-number" > 0< / span > ].value.op = < span class = "hljs-number" > 47< / span >
e.args[< span class = "hljs-number" > 0< / span > ].value.x.< span class = "hljs-keyword" > type< / span > = eval.Var
e.args[< span class = "hljs-number" > 0< / span > ].value.x.value = < span class = "hljs-string" > " A" < / span >
e.args[< span class = "hljs-number" > 0< / span > ].value.y.< span class = "hljs-keyword" > type< / span > = eval.Var
e.args[< span class = "hljs-number" > 0< / span > ].value.y.value = < span class = "hljs-string" > " pi" < / span >
< / code > < / pre >
< p > 在 可 能 的 情 況 下 , 你 應 該 避 免 在 一 個 包 中 暴 露 和 反 射 相 關 的 接 口 。 我 們 將 定 義 一 個 未 導 出 的 display函 數 用 於 遞 歸 處 理 工 作 , 導 出 的 是 Display函 數 , 它 隻 是 display函 數 簡 單 的 包 裝 以 接 受 interface{}類 型 的 參 數 : < / p >
< pre > < code class = "lang-Go" > gopl.io/ch12/display
< span class = "hljs-keyword" > func< / span > Display(name < span class = "hljs-typename" > string< / span > , x < span class = "hljs-keyword" > interface< / span > {}) {
fmt.Printf(< span class = "hljs-string" > " Display %s (%T):\n" < / span > , name, x)
display(name, reflect.ValueOf(x))
}
< / code > < / pre >
< p > 在 display函 數 中 , 我 們 使 用 了 前 面 定 義 的 打 印 基 礎 類 型 — — 基 本 類 型 、 函 數 和 chan等 — — 元 素 值 的 formatAtom函 數 , 但 是 我 們 會 使 用 reflect.Value的 方 法 來 遞 歸 顯 示 聚 合 類 型 的 每 一 個 成 員 或 元 素 。 在 遞 歸 下 降 過 程 中 , path字 符 串 , 從 最 開 始 傳 入 的 起 始 值 ( 這 里 是 “ e” ) , 將 逐 步 增 長 以 表 示 如 何 達 到 當 前 值 ( 例 如 “ e.args[0].value” ) 。 < / p >
< p > 因 爲 我 們 不 再 模 擬 fmt.Sprint函 數 , 我 們 將 直 接 使 用 fmt包 來 簡 化 我 們 的 例 子 實 現 。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > display(path < span class = "hljs-typename" > string< / span > , v reflect.Value) {
< span class = "hljs-keyword" > switch< / span > v.Kind() {
< span class = "hljs-keyword" > case< / span > reflect.Invalid:
fmt.Printf(< span class = "hljs-string" > " %s = invalid\n" < / span > , path)
< span class = "hljs-keyword" > case< / span > reflect.Slice, reflect.Array:
< span class = "hljs-keyword" > for< / span > i := < span class = "hljs-number" > 0< / span > ; i < v.Len(); i++ {
display(fmt.Sprintf(< span class = "hljs-string" > " %s[%d]" < / span > , path, i), v.Index(i))
}
< span class = "hljs-keyword" > case< / span > reflect.Struct:
< span class = "hljs-keyword" > for< / span > i := < span class = "hljs-number" > 0< / span > ; i < v.NumField(); i++ {
fieldPath := fmt.Sprintf(< span class = "hljs-string" > " %s.%s" < / span > , path, v.Type().Field(i).Name)
display(fieldPath, v.Field(i))
}
< span class = "hljs-keyword" > case< / span > reflect.Map:
< span class = "hljs-keyword" > for< / span > _, key := < span class = "hljs-keyword" > range< / span > v.MapKeys() {
display(fmt.Sprintf(< span class = "hljs-string" > " %s[%s]" < / span > , path,
formatAtom(key)), v.MapIndex(key))
}
< span class = "hljs-keyword" > case< / span > reflect.Ptr:
< span class = "hljs-keyword" > if< / span > v.IsNil() {
fmt.Printf(< span class = "hljs-string" > " %s = nil\n" < / span > , path)
} < span class = "hljs-keyword" > else< / span > {
display(fmt.Sprintf(< span class = "hljs-string" > " (*%s)" < / span > , path), v.Elem())
}
< span class = "hljs-keyword" > case< / span > reflect.Interface:
< span class = "hljs-keyword" > if< / span > v.IsNil() {
fmt.Printf(< span class = "hljs-string" > " %s = nil\n" < / span > , path)
} < span class = "hljs-keyword" > else< / span > {
fmt.Printf(< span class = "hljs-string" > " %s.type = %s\n" < / span > , path, v.Elem().Type())
display(path+< span class = "hljs-string" > " .value" < / span > , v.Elem())
}
< span class = "hljs-keyword" > default< / span > : < span class = "hljs-comment" > // basic types, channels, funcs< / span >
fmt.Printf(< span class = "hljs-string" > " %s = %s\n" < / span > , path, formatAtom(v))
}
}
< / code > < / pre >
< p > 讓 我 們 針 對 不 同 類 型 分 别 討 論 。 < / p >
< p > < strong > Slice和 數 組 : < / strong > 兩 種 的 處 理 邏 輯 是 一 樣 的 。 Len方 法 返 迴 slice或 數 組 值 中 的 元 素 個 數 , Index(i)活 動 索 引 i對 應 的 元 素 , 返 迴 的 也 是 一 個 reflect.Value類 型 的 值 ; 如 果 索 引 i超 出 范 圍 的 話 將 導 致 panic異 常 , 這 些 行 爲 和 數 組 或 slice類 型 內 建 的 len(a)和 a[i]等 操 作 類 似 。 display針 對 序 列 中 的 每 個 元 素 遞 歸 調 用 自 身 處 理 , 我 們 通 過 在 遞 歸 處 理 時 向 path附 加 “ [i]” 來 表 示 訪 問 路 徑 。 < / p >
< p > 雖 然 reflect.Value類 型 帶 有 很 多 方 法 , 但 是 隻 有 少 數 的 方 法 對 任 意 值 都 是 可 以 安 全 調 用 的 。 例 如 , Index方 法 隻 能 對 Slice、 數 組 或 字 符 串 類 型 的 值 調 用 , 其 它 類 型 如 果 調 用 將 導 致 panic異 常 。 < / p >
< p > < strong > 結 構 體 : < / strong > NumField方 法 報 告 結 構 體 中 成 員 的 數 量 , Field(i)以 reflect.Value類 型 返 迴 第 i個 成 員 的 值 。 成 員 列 表 包 含 了 匿 名 成 員 在 內 的 全 部 成 員 。 通 過 在 path添 加 “ .f” 來 表 示 成 員 路 徑 , 我 們 必 鬚 獲 得 結 構 體 對 應 的 reflect.Type類 型 信 息 , 包 含 結 構 體 類 型 和 第 i個 成 員 的 名 字 。 < / p >
< p > < strong > Maps:< / strong > MapKeys方 法 返 迴 一 個 reflect.Value類 型 的 slice, 每 一 個 都 對 應 map的 可 以 。 和 往 常 一 樣 , 遍 歷 map時 順 序 是 隨 機 的 。 MapIndex(key)返 迴 map中 key對 應 的 value。 我 們 向 path添 加 “ [key]” 來 表 示 訪 問 路 徑 。 ( 我 們 這 里 有 一 個 未 完 成 的 工 作 。 其 實 map的 key的 類 型 併 不 局 限 於 formatAtom能 完 美 處 理 的 類 型 ; 數 組 、 結 構 體 和 接 口 都 可 以 作 爲 map的 key。 針 對 這 種 類 型 , 完 善 key的 顯 示 信 息 是 練 習 12.1的 任 務 。 ) < / p >
< p > < strong > 指 針 : < / strong > Elem方 法 返 迴 指 針 指 向 的 變 量 , 還 是 reflect.Value類 型 。 技 術 指 針 是 nil, 這 個 操 作 也 是 安 全 的 , 在 這 種 情 況 下 指 針 是 Invalid無 效 類 型 , 但 是 我 們 可 以 用 IsNil方 法 來 顯 式 地 測 試 一 個 空 指 針 , 這 樣 我 們 可 以 打 印 更 合 適 的 信 息 。 我 們 在 path前 面 添 加 “ *” , 併 用 括 弧 包 含 以 避 免 歧 義 。 < / p >
< p > < strong > 接 口 : < / strong > 再 一 次 , 我 們 使 用 IsNil方 法 來 測 試 接 口 是 否 是 nil, 如 果 不 是 , 我 們 可 以 調 用 v.Elem()來 獲 取 接 口 對 應 的 動 態 值 , 併 且 打 印 對 應 的 類 型 和 值 。 < / p >
< p > 現 在 我 們 的 Display函 數 總 算 完 工 了 , 讓 我 們 看 看 它 的 表 現 吧 。 下 面 的 Movie類 型 是 在 4.5節 的 電 影 類 型 上 演 變 來 的 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > type< / span > Movie < span class = "hljs-keyword" > struct< / span > {
Title, Subtitle < span class = "hljs-typename" > string< / span >
Year < span class = "hljs-typename" > int< / span >
Color < span class = "hljs-typename" > bool< / span >
Actor < span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > string< / span >
Oscars []< span class = "hljs-typename" > string< / span >
Sequel *< span class = "hljs-typename" > string< / span >
}
< / code > < / pre >
< p > 讓 我 們 聲 明 一 個 該 類 型 的 變 量 , 然 後 看 看 Display函 數 如 何 顯 示 它 : < / p >
< pre > < code class = "lang-Go" > strangelove := Movie{
Title: < span class = "hljs-string" > " Dr. Strangelove" < / span > ,
Subtitle: < span class = "hljs-string" > " How I Learned to Stop Worrying and Love the Bomb" < / span > ,
Year: < span class = "hljs-number" > 1964< / span > ,
Color: < span class = "hljs-constant" > false< / span > ,
Actor: < span class = "hljs-keyword" > map< / span > [< span class = "hljs-typename" > string< / span > ]< span class = "hljs-typename" > string< / span > {
< span class = "hljs-string" > " Dr. Strangelove" < / span > : < span class = "hljs-string" > " Peter Sellers" < / span > ,
< span class = "hljs-string" > " Grp. Capt. Lionel Mandrake" < / span > : < span class = "hljs-string" > " Peter Sellers" < / span > ,
< span class = "hljs-string" > " Pres. Merkin Muffley" < / span > : < span class = "hljs-string" > " Peter Sellers" < / span > ,
< span class = "hljs-string" > " Gen. Buck Turgidson" < / span > : < span class = "hljs-string" > " George C. Scott" < / span > ,
< span class = "hljs-string" > " Brig. Gen. Jack D. Ripper" < / span > : < span class = "hljs-string" > " Sterling Hayden" < / span > ,
< span class = "hljs-string" > `Maj. T.J. " King" Kong`< / span > : < span class = "hljs-string" > " Slim Pickens" < / span > ,
},
Oscars: []< span class = "hljs-typename" > string< / span > {
< span class = "hljs-string" > " Best Actor (Nomin.)" < / span > ,
< span class = "hljs-string" > " Best Adapted Screenplay (Nomin.)" < / span > ,
< span class = "hljs-string" > " Best Director (Nomin.)" < / span > ,
< span class = "hljs-string" > " Best Picture (Nomin.)" < / span > ,
},
}
< / code > < / pre >
< p > Display(" strangelove" , strangelove)調 用 將 顯 示 ( strangelove電 影 對 應 的 中 文 名 是 《 奇 愛 博 士 》 ) : < / p >
< pre > < code class = "lang-Go" > Display strangelove (display.Movie):
strangelove.Title = < span class = "hljs-string" > " Dr. Strangelove" < / span >
strangelove.Subtitle = < span class = "hljs-string" > " How I Learned to Stop Worrying and Love the Bomb" < / span >
strangelove.Year = < span class = "hljs-number" > 1964< / span >
strangelove.Color = < span class = "hljs-constant" > false< / span >
strangelove.Actor[< span class = "hljs-string" > " Gen. Buck Turgidson" < / span > ] = < span class = "hljs-string" > " George C. Scott" < / span >
strangelove.Actor[< span class = "hljs-string" > " Brig. Gen. Jack D. Ripper" < / span > ] = < span class = "hljs-string" > " Sterling Hayden" < / span >
strangelove.Actor[< span class = "hljs-string" > " Maj. T.J. \" King\" Kong" < / span > ] = < span class = "hljs-string" > " Slim Pickens" < / span >
strangelove.Actor[< span class = "hljs-string" > " Dr. Strangelove" < / span > ] = < span class = "hljs-string" > " Peter Sellers" < / span >
strangelove.Actor[< span class = "hljs-string" > " Grp. Capt. Lionel Mandrake" < / span > ] = < span class = "hljs-string" > " Peter Sellers" < / span >
strangelove.Actor[< span class = "hljs-string" > " Pres. Merkin Muffley" < / span > ] = < span class = "hljs-string" > " Peter Sellers" < / span >
strangelove.Oscars[< span class = "hljs-number" > 0< / span > ] = < span class = "hljs-string" > " Best Actor (Nomin.)" < / span >
strangelove.Oscars[< span class = "hljs-number" > 1< / span > ] = < span class = "hljs-string" > " Best Adapted Screenplay (Nomin.)" < / span >
strangelove.Oscars[< span class = "hljs-number" > 2< / span > ] = < span class = "hljs-string" > " Best Director (Nomin.)" < / span >
strangelove.Oscars[< span class = "hljs-number" > 3< / span > ] = < span class = "hljs-string" > " Best Picture (Nomin.)" < / span >
strangelove.Sequel = < span class = "hljs-constant" > nil< / span >
< / code > < / pre >
< p > 我 們 也 可 以 使 用 Display函 數 來 顯 示 標 準 庫 中 類 型 的 內 部 結 構 , 例 如 < code > *os.File< / code > 類 型 : < / p >
< pre > < code class = "lang-Go" > Display(< span class = "hljs-string" > " os.Stderr" < / span > , os.Stderr)
< span class = "hljs-comment" > // Output:< / span >
< span class = "hljs-comment" > // Display os.Stderr (*os.File):< / span >
< span class = "hljs-comment" > // (*(*os.Stderr).file).fd = 2< / span >
< span class = "hljs-comment" > // (*(*os.Stderr).file).name = " /dev/stderr" < / span >
< span class = "hljs-comment" > // (*(*os.Stderr).file).nepipe = 0< / span >
< / code > < / pre >
< p > 要 註 意 的 是 , 結 構 體 中 未 導 出 的 成 員 對 反 射 也 是 可 見 的 。 需 要 當 心 的 是 這 個 例 子 的 輸 出 在 不 同 操 作 繫 統 上 可 能 是 不 同 的 , 併 且 隨 着 標 準 庫 的 發 展 也 可 能 導 致 結 果 不 同 。 ( 這 也 是 將 這 些 成 員 定 義 爲 私 有 成 員 的 原 因 之 一 ! ) 我 們 深 圳 可 以 用 Display函 數 來 顯 示 reflect.Value, 來 査 看 < code > *os.File< / code > 類 型 的 內 部 表 示 方 式 。 < code > Display(" rV" , reflect.ValueOf(os.Stderr))< / code > 調 用 的 輸 出 如 下 , 當 然 不 同 環 境 得 到 的 結 果 可 能 有 差 異 : < / p >
< pre > < code class = "lang-Go" > Display rV (reflect.Value):
(*rV.typ).size = < span class = "hljs-number" > 8< / span >
(*rV.typ).hash = < span class = "hljs-number" > 871609668< / span >
(*rV.typ).align = < span class = "hljs-number" > 8< / span >
(*rV.typ).fieldAlign = < span class = "hljs-number" > 8< / span >
(*rV.typ).kind = < span class = "hljs-number" > 22< / span >
(*(*rV.typ).< span class = "hljs-typename" > string< / span > ) = < span class = "hljs-string" > " *os.File" < / span >
(*(*(*rV.typ).uncommonType).methods[< span class = "hljs-number" > 0< / span > ].name) = < span class = "hljs-string" > " Chdir" < / span >
(*(*(*(*rV.typ).uncommonType).methods[< span class = "hljs-number" > 0< / span > ].mtyp).< span class = "hljs-typename" > string< / span > ) = < span class = "hljs-string" > " func() error" < / span >
(*(*(*(*rV.typ).uncommonType).methods[< span class = "hljs-number" > 0< / span > ].typ).< span class = "hljs-typename" > string< / span > ) = < span class = "hljs-string" > " func(*os.File) error" < / span >
...
< / code > < / pre >
< p > 觀 察 下 面 兩 個 例 子 的 區 别 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > var< / span > i < span class = "hljs-keyword" > interface< / span > {} = < span class = "hljs-number" > 3< / span >
Display(< span class = "hljs-string" > " i" < / span > , i)
< span class = "hljs-comment" > // Output:< / span >
< span class = "hljs-comment" > // Display i (int):< / span >
< span class = "hljs-comment" > // i = 3< / span >
Display(< span class = "hljs-string" > " & i" < / span > , & i)
< span class = "hljs-comment" > // Output:< / span >
< span class = "hljs-comment" > // Display & i (*interface {}):< / span >
< span class = "hljs-comment" > // (*& i).type = int< / span >
< span class = "hljs-comment" > // (*& i).value = 3< / span >
< / code > < / pre >
< p > 在 第 一 個 例 子 中 , Display函 數 將 調 用 reflect.ValueOf(i), 它 返 迴 一 個 Int類 型 的 值 。 正 如 我 們 在 12.2節 中 提 到 的 , reflect.ValueOf總 是 返 迴 一 個 值 的 具 體 類 型 , 因 爲 它 是 從 一 個 接 口 值 提 取 的 內 容 。 < / p >
< p > 在 第 二 個 例 子 中 , Display函 數 調 用 的 是 reflect.ValueOf(& i), 它 返 迴 一 個 指 向 i的 指 針 , 對 應 Ptr類 型 。 在 switch的 Ptr分 支 中 , 通 過 調 用 Elem來 返 迴 這 個 值 , 返 迴 一 個 Value來 表 示 i, 對 應 Interface類 型 。 一 個 間 接 獲 得 的 Value, 就 像 這 一 個 , 可 能 代 表 任 意 類 型 的 值 , 包 括 接 口 類 型 。 內 部 的 display函 數 遞 歸 調 用 自 身 , 這 次 它 將 打 印 接 口 的 動 態 類 型 和 值 。 < / p >
< p > 目 前 的 實 現 , Display如 果 顯 示 一 個 帶 環 的 數 據 結 構 將 會 陷 入 死 循 環 , 例 如 首 位 項 鏈 的 鏈 表 : < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-comment" > // a struct that points to itself< / span >
< span class = "hljs-keyword" > type< / span > Cycle < span class = "hljs-keyword" > struct< / span > { Value < span class = "hljs-typename" > int< / span > ; Tail *Cycle }
< span class = "hljs-keyword" > var< / span > c Cycle
c = Cycle{< span class = "hljs-number" > 42< / span > , & c}
Display(< span class = "hljs-string" > " c" < / span > , c)
< / code > < / pre >
< p > Display會 永 遠 不 停 地 進 行 深 度 遞 歸 打 印 : < / p >
< pre > < code class = "lang-Go" > Display c (display.Cycle):
c.Value = < span class = "hljs-number" > 42< / span >
(*c.Tail).Value = < span class = "hljs-number" > 42< / span >
(*(*c.Tail).Tail).Value = < span class = "hljs-number" > 42< / span >
(*(*(*c.Tail).Tail).Tail).Value = < span class = "hljs-number" > 42< / span >
...ad infinitum...
< / code > < / pre >
< p > 許 多 Go語 言 程 序 都 包 含 了 一 些 循 環 的 數 據 結 果 。 Display支 持 這 類 帶 環 的 數 據 結 構 是 比 較 棘 手 的 , 需 要 增 加 一 個 額 外 的 記 録 訪 問 的 路 徑 ; 代 價 是 昂 貴 的 。 一 般 的 解 決 方 案 是 采 用 不 安 全 的 語 言 特 性 , 我 們 將 在 13.3節 看 到 具 體 的 解 決 方 案 。 < / p >
< p > 帶 環 的 數 據 結 構 很 少 會 對 fmt.Sprint函 數 造 成 問 題 , 因 爲 它 很 少 嚐 試 打 印 完 整 的 數 據 結 構 。 例 如 , 當 它 遇 到 一 個 指 針 的 時 候 , 它 隻 是 簡 單 第 打 印 指 針 的 數 值 。 雖 然 , 在 打 印 包 含 自 身 的 slice或 map時 可 能 遇 到 睏 難 , 但 是 不 保 證 處 理 這 種 是 罕 見 情 況 卻 可 以 避 免 額 外 的 麻 煩 。 < / p >
< p > < strong > 練 習 12.1: < / strong > 擴 展 Displayhans, 以 便 它 可 以 顯 示 包 含 以 結 構 體 或 數 組 作 爲 map的 key類 型 的 值 。 < / p >
< p > < strong > 練 習 12.2: < / strong > 增 強 display函 數 的 穩 健 性 , 通 過 記 録 邊 界 的 步 數 來 確 保 在 超 出 一 定 限 製 前 放 棄 遞 歸 。 ( 在 13.3節 , 我 們 會 看 到 另 一 種 探 測 數 據 結 構 是 否 存 在 環 的 技 術 。 ) < / p >
2015-12-09 07:57:17 +00:00
< / section >
< / div >
< / div >
< / div >
< a href = "../ch12/ch12-02.html" class = "navigation navigation-prev " aria-label = "Previous page: reflect.Type和reflect.Value" > < i class = "fa fa-angle-left" > < / i > < / a >
2015-12-21 04:55:18 +00:00
< a href = "../ch12/ch12-04.html" class = "navigation navigation-next " aria-label = "Next page: 示例: 編碼S表達式" > < 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 >