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 > 示例: 解碼S表達式 | 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-07.html" / >
< link rel = "prev" href = "../ch12/ch12-05.html" / >
< / head >
< body >
2016-01-02 08:04:45 +00:00
< div class = "book"
data-level="12.6"
data-chapter-title="示例: 解碼S表達式"
data-filepath="ch12/ch12-06.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 " 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 active" 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-21 04:55:18 +00:00
< h2 id = "126-示例-解碼s表達式" > 12.6. 示 例 : 解 碼 S表 達 式 < / h2 >
2016-01-02 08:04:45 +00:00
< p > 標 準 庫 中 encoding/...下 每 個 包 中 提 供 的 Marshal編 碼 函 數 都 有 一 個 對 應 的 Unmarshal函 數 用 於 解 碼 。 例 如 , 我 們 在 4.5節 中 看 到 的 , 要 將 包 含 JSON編 碼 格 式 的 字 節 slice數 據 解 碼 爲 我 們 自 己 的 Movie類 型 ( § 12.3) , 我 們 可 以 這 樣 做 : < / p >
< pre > < code class = "lang-Go" > data := []< span class = "hljs-typename" > byte< / span > {< span class = "hljs-comment" > /* ... */< / span > }
< span class = "hljs-keyword" > var< / span > movie Movie
err := json.Unmarshal(data, & movie)
< / code > < / pre >
< p > Unmarshal函 數 使 用 了 反 射 機 製 類 脩 改 movie變 量 的 每 個 成 員 , 根 據 輸 入 的 內 容 爲 Movie成 員 創 建 對 應 的 map、 結 構 體 和 slice。 < / p >
< p > 現 在 讓 我 們 爲 S表 達 式 編 碼 實 現 一 個 簡 易 的 Unmarshal, 類 似 於 前 面 的 json.Unmarshal標 準 庫 函 數 , 對 應 我 們 之 前 實 現 的 sexpr.Marshal函 數 的 逆 操 作 。 我 們 必 鬚 提 醒 一 下 , 一 個 健 壯 的 和 通 用 的 實 現 通 常 需 要 比 例 子 更 多 的 代 碼 , 爲 了 便 於 演 示 我 們 采 用 了 精 簡 的 實 現 。 我 們 隻 支 持 S表 達 式 有 限 的 子 集 , 同 時 處 理 錯 誤 的 方 式 也 比 較 粗 暴 , 代 碼 的 目 的 是 爲 了 演 示 反 射 的 用 法 , 而 不 是 構 造 一 個 實 用 的 S表 達 式 的 解 碼 器 。 < / p >
< p > 詞 法 分 析 器 lexer使 用 了 標 準 庫 中 的 text/scanner包 將 輸 入 流 的 字 節 數 據 解 析 爲 一 個 個 類 似 註 釋 、 標 識 符 、 字 符 串 面 值 和 數 字 面 值 之 類 的 標 記 。 輸 入 掃 描 器 scanner的 Scan方 法 將 提 前 掃 描 和 返 迴 下 一 個 記 號 , 對 於 rune類 型 。 大 多 數 記 號 , 比 如 “ (” , 對 應 一 個 單 一 rune可 表 示 的 Unicode字 符 , 但 是 text/scanner也 可 以 用 小 的 負 數 表 示 記 號 標 識 符 、 字 符 串 等 由 多 個 字 符 組 成 的 記 號 。 調 用 Scan方 法 將 返 迴 這 些 記 號 的 類 型 , 接 着 調 用 TokenText方 法 將 返 迴 記 號 對 應 的 文 本 內 容 。 < / p >
< p > 因 爲 每 個 解 析 器 可 能 需 要 多 次 使 用 當 前 的 記 號 , 但 是 Scan會 一 直 向 前 掃 描 , 所 有 我 們 包 裝 了 一 個 lexer掃 描 器 輔 助 類 型 , 用 於 跟 蹤 最 近 由 Scan方 法 返 迴 的 記 號 。 < / p >
< pre > < code class = "lang-Go" > gopl.io/ch12/sexpr
< span class = "hljs-keyword" > type< / span > lexer < span class = "hljs-keyword" > struct< / span > {
scan scanner.Scanner
token < span class = "hljs-typename" > rune< / span > < span class = "hljs-comment" > // the current token< / span >
}
< span class = "hljs-keyword" > func< / span > (lex *lexer) next() { lex.token = lex.scan.Scan() }
< span class = "hljs-keyword" > func< / span > (lex *lexer) text() < span class = "hljs-typename" > string< / span > { < span class = "hljs-keyword" > return< / span > lex.scan.TokenText() }
< span class = "hljs-keyword" > func< / span > (lex *lexer) consume(want < span class = "hljs-typename" > rune< / span > ) {
< span class = "hljs-keyword" > if< / span > lex.token != want { < span class = "hljs-comment" > // < span class = "hljs-doctag" > NOTE:< / span > Not an example of good error handling.< / span >
< span class = "hljs-built_in" > panic< / span > (fmt.Sprintf(< span class = "hljs-string" > " got %q, want %q" < / span > , lex.text(), want))
}
lex.next()
}
< / code > < / pre >
< p > 現 在 讓 我 們 轉 到 語 法 解 析 器 。 它 主 要 包 含 兩 個 功 能 。 第 一 個 是 read函 數 , 用 於 讀 取 S表 達 式 的 當 前 標 記 , 然 後 根 據 S表 達 式 的 當 前 標 記 更 新 可 取 地 址 的 reflect.Value對 應 的 變 量 v。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > read(lex *lexer, v reflect.Value) {
< span class = "hljs-keyword" > switch< / span > lex.token {
< span class = "hljs-keyword" > case< / span > scanner.Ident:
< span class = "hljs-comment" > // The only valid identifiers are< / span >
< span class = "hljs-comment" > // " nil" and struct field names.< / span >
< span class = "hljs-keyword" > if< / span > lex.text() == < span class = "hljs-string" > " nil" < / span > {
v.Set(reflect.Zero(v.Type()))
lex.next()
< span class = "hljs-keyword" > return< / span >
}
< span class = "hljs-keyword" > case< / span > scanner.String:
s, _ := strconv.Unquote(lex.text()) < span class = "hljs-comment" > // < span class = "hljs-doctag" > NOTE:< / span > ignoring errors< / span >
v.SetString(s)
lex.next()
< span class = "hljs-keyword" > return< / span >
< span class = "hljs-keyword" > case< / span > scanner.Int:
i, _ := strconv.Atoi(lex.text()) < span class = "hljs-comment" > // < span class = "hljs-doctag" > NOTE:< / span > ignoring errors< / span >
v.SetInt(< span class = "hljs-typename" > int64< / span > (i))
lex.next()
< span class = "hljs-keyword" > return< / span >
< span class = "hljs-keyword" > case< / span > < span class = "hljs-string" > ' (' < / span > :
lex.next()
readList(lex, v)
lex.next() < span class = "hljs-comment" > // consume ' )' < / span >
< span class = "hljs-keyword" > return< / span >
}
< span class = "hljs-built_in" > panic< / span > (fmt.Sprintf(< span class = "hljs-string" > " unexpected token %q" < / span > , lex.text()))
}
< / code > < / pre >
< p > 我 們 的 S表 達 式 使 用 標 識 符 區 分 兩 個 不 同 類 型 , 結 構 體 成 員 名 和 nil值 的 指 針 。 read函 數 值 處 理 nil類 型 的 標 識 符 。 當 遇 到 scanner.Ident爲 “ nil” 是 , 使 用 reflect.Zero函 數 將 變 量 v設 置 爲 零 值 。 而 其 它 任 何 類 型 的 標 識 符 , 我 們 都 作 爲 錯 誤 處 理 。 後 面 的 readList函 數 將 處 理 結 構 體 的 成 員 名 。 < / p >
< p > 一 個 “ (” 標 記 對 應 一 個 列 表 的 開 始 。 第 二 個 函 數 readList, 將 一 個 列 表 解 碼 到 一 個 聚 合 類 型 中 ( map、 結 構 體 、 slice或 數 組 ) , 具 體 類 型 依 然 於 傳 入 待 填 充 變 量 的 類 型 。 每 次 遇 到 這 種 情 況 , 循 環 繼 續 解 析 每 個 元 素 直 到 遇 到 於 開 始 標 記 匹 配 的 結 束 標 記 “ )” , endList函 數 用 於 檢 測 結 束 標 記 。 < / p >
< p > 最 有 趣 的 部 分 是 遞 歸 。 最 簡 單 的 是 對 數 組 類 型 的 處 理 。 直 到 遇 到 “ )” 結 束 標 記 , 我 們 使 用 Index函 數 來 獲 取 數 組 每 個 元 素 的 地 址 , 然 後 遞 歸 調 用 read函 數 處 理 。 和 其 它 錯 誤 類 似 , 如 果 輸 入 數 據 導 致 解 碼 器 的 引 用 超 出 了 數 組 的 范 圍 , 解 碼 器 將 拋 出 panic異 常 。 slice也 采 用 類 似 方 法 解 析 , 不 同 的 是 我 們 將 爲 每 個 元 素 創 建 新 的 變 量 , 然 後 將 元 素 添 加 到 slice的 末 尾 。 < / p >
< p > 在 循 環 處 理 結 構 體 和 map每 個 元 素 時 必 鬚 解 碼 一 個 (key value)格 式 的 對 應 子 列 表 。 對 於 結 構 體 , key部 分 對 於 成 員 的 名 字 。 和 數 組 類 似 , 我 們 使 用 FieldByName找 到 結 構 體 對 應 成 員 的 變 量 , 然 後 遞 歸 調 用 read函 數 處 理 。 對 於 map, key可 能 是 任 意 類 型 , 對 元 素 的 處 理 方 式 和 slice類 似 , 我 們 創 建 一 個 新 的 變 量 , 然 後 遞 歸 填 充 它 , 最 後 將 新 解 析 到 的 key/value對 添 加 到 map。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-keyword" > func< / span > readList(lex *lexer, v reflect.Value) {
< span class = "hljs-keyword" > switch< / span > v.Kind() {
< span class = "hljs-keyword" > case< / span > reflect.Array: < span class = "hljs-comment" > // (item ...)< / span >
< span class = "hljs-keyword" > for< / span > i := < span class = "hljs-number" > 0< / span > ; !endList(lex); i++ {
read(lex, v.Index(i))
}
< span class = "hljs-keyword" > case< / span > reflect.Slice: < span class = "hljs-comment" > // (item ...)< / span >
< span class = "hljs-keyword" > for< / span > !endList(lex) {
item := reflect.New(v.Type().Elem()).Elem()
read(lex, item)
v.Set(reflect.Append(v, item))
}
< span class = "hljs-keyword" > case< / span > reflect.Struct: < span class = "hljs-comment" > // ((name value) ...)< / span >
< span class = "hljs-keyword" > for< / span > !endList(lex) {
lex.consume(< span class = "hljs-string" > ' (' < / span > )
< span class = "hljs-keyword" > if< / span > lex.token != scanner.Ident {
< span class = "hljs-built_in" > panic< / span > (fmt.Sprintf(< span class = "hljs-string" > " got token %q, want field name" < / span > , lex.text()))
}
name := lex.text()
lex.next()
read(lex, v.FieldByName(name))
lex.consume(< span class = "hljs-string" > ' )' < / span > )
}
< span class = "hljs-keyword" > case< / span > reflect.Map: < span class = "hljs-comment" > // ((key value) ...)< / span >
v.Set(reflect.MakeMap(v.Type()))
< span class = "hljs-keyword" > for< / span > !endList(lex) {
lex.consume(< span class = "hljs-string" > ' (' < / span > )
key := reflect.New(v.Type().Key()).Elem()
read(lex, key)
value := reflect.New(v.Type().Elem()).Elem()
read(lex, value)
v.SetMapIndex(key, value)
lex.consume(< span class = "hljs-string" > ' )' < / span > )
}
< span class = "hljs-keyword" > default< / span > :
< span class = "hljs-built_in" > panic< / span > (fmt.Sprintf(< span class = "hljs-string" > " cannot decode list into %v" < / span > , v.Type()))
}
}
< span class = "hljs-keyword" > func< / span > endList(lex *lexer) < span class = "hljs-typename" > bool< / span > {
< span class = "hljs-keyword" > switch< / span > lex.token {
< span class = "hljs-keyword" > case< / span > scanner.EOF:
< span class = "hljs-built_in" > panic< / span > (< span class = "hljs-string" > " end of file" < / span > )
< span class = "hljs-keyword" > case< / span > < span class = "hljs-string" > ' )' < / span > :
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > true< / span >
}
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > false< / span >
}
< / code > < / pre >
< p > 最 後 , 我 們 將 解 析 器 包 裝 爲 導 出 的 Unmarshal解 碼 函 數 , 隱 藏 了 一 些 初 始 化 和 清 理 等 邊 緣 處 理 。 內 部 解 析 器 以 panic的 方 式 拋 出 錯 誤 , 但 是 Unmarshal函 數 通 過 在 defer語 句 調 用 recover函 數 來 捕 獲 內 部 panic( § 5.10) , 然 後 返 迴 一 個 對 panic對 應 的 錯 誤 信 息 。 < / p >
< pre > < code class = "lang-Go" > < span class = "hljs-comment" > // Unmarshal parses S-expression data and populates the variable< / span >
< span class = "hljs-comment" > // whose address is in the non-nil pointer out.< / span >
< span class = "hljs-keyword" > func< / span > Unmarshal(data []< span class = "hljs-typename" > byte< / span > , out < span class = "hljs-keyword" > interface< / span > {}) (err error) {
lex := & lexer{scan: scanner.Scanner{Mode: scanner.GoTokens}}
lex.scan.Init(bytes.NewReader(data))
lex.next() < span class = "hljs-comment" > // get the first token< / span >
< span class = "hljs-keyword" > defer< / span > < span class = "hljs-keyword" > func< / span > () {
< span class = "hljs-comment" > // < span class = "hljs-doctag" > NOTE:< / span > this is not an example of ideal error handling.< / span >
< span class = "hljs-keyword" > if< / span > x := < span class = "hljs-built_in" > recover< / span > (); x != < span class = "hljs-constant" > nil< / span > {
err = fmt.Errorf(< span class = "hljs-string" > " error at %s: %v" < / span > , lex.scan.Position, x)
}
}()
read(lex, reflect.ValueOf(out).Elem())
< span class = "hljs-keyword" > return< / span > < span class = "hljs-constant" > nil< / span >
}
< / code > < / pre >
< p > 生 産 實 現 不 應 該 對 任 何 輸 入 問 題 都 用 panic形 式 報 告 , 而 且 應 該 報 告 一 些 錯 誤 相 關 的 信 息 , 例 如 出 現 錯 誤 輸 入 的 行 號 和 位 置 等 。 盡 管 如 此 , 我 們 希 望 通 過 這 個 例 子 來 展 示 類 似 encoding/json等 包 底 層 代 碼 的 實 現 思 路 , 以 及 如 何 使 用 反 射 機 製 來 填 充 數 據 結 構 。 < / p >
< p > < strong > 練 習 12.8: < / strong > sexpr.Unmarshal函 數 和 json.Marshal一 樣 ( 譯 註 : 這 可 能 是 筆 誤 , 我 覺 得 應 該 是 指 < code > json.Unmarshal< / code > 函 數 ) , 都 要 求 在 解 碼 前 輸 入 完 整 的 字 節 slice。 定 義 一 個 和 json.Decoder類 似 的 sexpr.Decoder類 型 , 支 持 從 一 個 io.Reader流 解 碼 。 脩 改 sexpr.Unmarshal函 數 , 使 用 這 個 新 的 類 型 實 現 。 < / p >
< p > < strong > 練 習 12.9: < / strong > 編 寫 一 個 基 於 標 記 的 API用 於 解 碼 S表 達 式 , 參 考 xml.Decoder( 7.14) 的 風 格 。 你 將 需 要 五 種 類 型 的 標 記 : Symbol、 String、 Int、 StartList和 EndList。 < / p >
< p > < strong > 練 習 12.10: < / strong > 擴 展 sexpr.Unmarshal函 數 , 支 持 布 爾 型 、 浮 點 數 和 interface類 型 的 解 碼 , 使 用 < strong > 練 習 12.3: < / strong > 的 方 案 。 ( 提 示 : 要 解 碼 接 口 , 你 需 要 將 name映 射 到 每 個 支 持 類 型 的 reflect.Type。 ) < / p >
2015-12-09 07:57:17 +00:00
< / section >
< / div >
< / div >
< / div >
< a href = "../ch12/ch12-05.html" class = "navigation navigation-prev " aria-label = "Previous page: 通過reflect.Value脩改值" > < i class = "fa fa-angle-left" > < / i > < / a >
2015-12-28 08:08:26 +00:00
< a href = "../ch12/ch12-07.html" class = "navigation navigation-next " aria-label = "Next page: 獲取結構體字段標識" > < 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 >