mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-08-05 07:11:52 +00:00
fix typo and optimize.
Change-Id: I7b6938936231fd722814984678ffa30402539fd9
This commit is contained in:
@@ -1,23 +1,23 @@
|
||||
## 12.4. 示例: 编码S表达式
|
||||
## 12.4. 示例: 编码为S表达式
|
||||
|
||||
Display是一个用于显示结构化数据的调试工具,但是它并不能将任意的Go语言对象编码为通用消息然后用于进程间通信。
|
||||
|
||||
正如我们在4.5节中中看到的,Go语言的标准库支持了包括JSON、XML和ASN.1等多种编码格式。还有另一种依然被广泛使用的格式是S表达式格式,采用类似Lisp语言的语法。但是和其他编码格式不同的是,Go语言自带的标准库并不支持S表达式,主要是因为它没有一个公认的标准规范。
|
||||
正如我们在4.5节中中看到的,Go语言的标准库支持了包括JSON、XML和ASN.1等多种编码格式。还有另一种依然被广泛使用的格式是S表达式格式,采用Lisp语言的语法。但是和其他编码格式不同的是,Go语言自带的标准库并不支持S表达式,主要是因为它没有一个公认的标准规范。
|
||||
|
||||
在本节中,我们将定义一个包用于将Go语言的对象编码为S表达式格式,它支持以下结构:
|
||||
在本节中,我们将定义一个包用于将任意的Go语言对象编码为S表达式格式,它支持以下结构:
|
||||
|
||||
```
|
||||
42 integer
|
||||
"hello" string (with Go-style quotation)
|
||||
foo symbol (an unquoted name)
|
||||
(1 2 3) list (zero or more items enclosed in parentheses)
|
||||
"hello" string (带有Go风格的引号)
|
||||
foo symbol (未用引号括起来的名字)
|
||||
(1 2 3) list (括号包起来的0个或多个元素)
|
||||
```
|
||||
|
||||
布尔型习惯上使用t符号表示true,空列表或nil符号表示false,但是为了简单起见,我们暂时忽略布尔类型。同时忽略的还有chan管道和函数,因为通过反射并无法知道它们的确切状态。我们忽略的还浮点数、复数和interface。支持它们是练习12.3的任务。
|
||||
布尔型习惯上使用t符号表示true,空列表或nil符号表示false,但是为了简单起见,我们暂时忽略布尔类型。同时忽略的还有chan管道和函数,因为通过反射并无法知道它们的确切状态。我们忽略的还有浮点数、复数和interface。支持它们是练习12.3的任务。
|
||||
|
||||
我们将Go语言的类型编码为S表达式的方法如下。整数和字符串以自然的方式编码。Nil值编码为nil符号。数组和slice被编码为一个列表。
|
||||
我们将Go语言的类型编码为S表达式的方法如下。整数和字符串以显而易见的方式编码。空值编码为nil符号。数组和slice被编码为列表。
|
||||
|
||||
结构体被编码为成员对象的列表,每个成员对象对应一个个仅有两个元素的子列表,其中子列表的第一个元素是成员的名字,子列表的第二个元素是成员的值。Map被编码为键值对的列表。传统上,S表达式使用点状符号列表(key . value)结构来表示key/value对,而不是用一个含双元素的列表,不过为了简单我们忽略了点状符号列表。
|
||||
结构体被编码为成员对象的列表,每个成员对象对应一个有两个元素的子列表,子列表的第一个元素是成员的名字,第二个元素是成员的值。Map被编码为键值对的列表。传统上,S表达式使用点状符号列表(key . value)结构来表示key/value对,而不是用一个含双元素的列表,不过为了简单我们忽略了点状符号列表。
|
||||
|
||||
编码是由一个encode递归函数完成,如下所示。它的结构本质上和前面的Display函数类似:
|
||||
|
||||
@@ -93,7 +93,7 @@ func encode(buf *bytes.Buffer, v reflect.Value) error {
|
||||
}
|
||||
```
|
||||
|
||||
Marshal函数是对encode的保证,以保持和encoding/...下其它包有着相似的API:
|
||||
Marshal函数是对encode的包装,以保持和encoding/...下其它包有着相似的API:
|
||||
|
||||
```Go
|
||||
// Marshal encodes a Go value in S-expression form.
|
||||
@@ -118,7 +118,7 @@ ge C. Scott") ("Brig. Gen. Jack D. Ripper" "Sterling Hayden") ("Maj. T.J. \
|
||||
omin.)" "Best Picture (Nomin.)")) (Sequel nil))
|
||||
```
|
||||
|
||||
整个输出编码为一行中以减少输出的大小,但是也很难阅读。这里有一个对S表达式格式化的约定。编写一个S表达式的格式化函数将作为一个具有挑战性的练习任务;不过 http://gopl.io 也提供了一个简单的版本。
|
||||
整个输出编码为一行中以减少输出的大小,但是也很难阅读。下面是对S表达式手动格式化的结果。编写一个S表达式的美化格式化函数将作为一个具有挑战性的练习任务;不过 http://gopl.io 也提供了一个简单的版本。
|
||||
|
||||
```
|
||||
((Title "Dr. Strangelove")
|
||||
@@ -139,7 +139,7 @@ omin.)" "Best Picture (Nomin.)")) (Sequel nil))
|
||||
|
||||
和fmt.Print、json.Marshal、Display函数类似,sexpr.Marshal函数处理带环的数据结构也会陷入死循环。
|
||||
|
||||
在12.6节中,我们将给出S表达式解码器的实现步骤,但是在那之前,我们还需要先了解如果通过反射技术来更新程序的变量。
|
||||
在12.6节中,我们将给出S表达式解码器的实现步骤,但是在那之前,我们还需要先了解如何通过反射技术来更新程序的变量。
|
||||
|
||||
**练习 12.3:** 实现encode函数缺少的分支。将布尔类型编码为t和nil,浮点数编码为Go语言的格式,复数1+2i编码为#C(1.0 2.0)格式。接口编码为类型名和值对,例如("[]int" (1 2 3)),但是这个形式可能会造成歧义:reflect.Type.String方法对于不同的类型可能返回相同的结果。
|
||||
|
||||
|
Reference in New Issue
Block a user