diff --git a/README.md b/README.md index 9e0bf03..71b1967 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## 翻译进度 -12.6 [用切片读写文件](eBook/12.6.md) +12.12 [Go 中的密码学](eBook/12.12.md) ## 支持本书 diff --git a/README_gc.md b/README_gc.md index fdf14cb..7327b6f 100644 --- a/README_gc.md +++ b/README_gc.md @@ -30,4 +30,4 @@ Golang 编程:245386165 |更新日期 |更新内容 |----------|------------------ -|2015-11-13|12.6 用切片读写文件 +|2015-11-18|12.12 Go 中的密码学 diff --git a/TOC.md b/TOC.md index 63a238d..c1df725 100644 --- a/TOC.md +++ b/TOC.md @@ -111,3 +111,9 @@ - 12.4 [从命令行读取参数](12.4.md) - 12.5 [用 buffer 读取文件](12.5.md) - 12.6 [用切片读写文件](12.6.md) + - 12.7 [用 defer 关闭文件](12.7.md) + - 12.8 [使用接口的实际例子:fmt.Fprintf](12.8.md) + - 12.9 [格式化 JSON 数据](12.9.md) + - 12.10 [XML 数据格式](12.10.md) + - 12.11 [用 Gob 传输数据](12.11.md) + - 12.12 [Go 中的密码学](12.12.md) diff --git a/eBook/12.10.md b/eBook/12.10.md index 4dcfe8b..ec610c5 100644 --- a/eBook/12.10.md +++ b/eBook/12.10.md @@ -1,6 +1,7 @@ # 12.10 XML 数据格式 下面是与 12.9 节 JSON 例子等价的 XML 版本: + ```xml Laura @@ -56,8 +57,11 @@ func main() { } } } +``` -/* Output: +输出: + +``` Token name: Person Token name: FirstName This is the content: Laura @@ -66,9 +70,8 @@ Token name: LastName This is the content: Lynn End of token End of token -*/ - ``` + 包中定义了若干 XML 标签类型:StartElement,Chardata(这是从开始标签到结束标签之间的实际文本),EndElement,Comment,Directive 或 ProcInst。 包中同样定义了一个结构解析器:`NewParser` 方法持有一个 io.Reader(这里具体类型是 strings.NewReader)并生成一个解析器类型的对象。还有一个 `Token()` 方法返回输入流里的下一个 XML token。在输入流的结尾处,会返回(nil,io.EOF) diff --git a/eBook/12.11.md b/eBook/12.11.md index bebc3d4..3036d17 100644 --- a/eBook/12.11.md +++ b/eBook/12.11.md @@ -16,7 +16,6 @@ Gob 文件或流是完全自描述的:里面包含的所有类型都有一个 ```go type T struct { X, Y, Z int } var t = T{X: 7, Y: 0, Z: 8} - ``` 而在接收者这边可以用一个结构体 U 类型的变量 u 来接收这个值: @@ -24,7 +23,6 @@ var t = T{X: 7, Y: 0, Z: 8} ```go type U struct { X, Y *int8 } var u U - ``` 在接收者中,X 的值是7,Y 的值是0(Y的值并没有从 t 中传递过来,因为它是零值) @@ -81,7 +79,6 @@ func main() { fmt.Printf("%q: {%d,%d}\n", q.Name, *q.X, *q.Y) } // Output: "Pythagoras": {3,4} - ``` 示例 12.19 [gob2.go](examples/chapter_12/gob2.go) 编码到文件: @@ -115,7 +112,7 @@ func main() { pa := &Address{"private", "Aartselaar","Belgium"} wa := &Address{"work", "Boom", "Belgium"} vc := VCard{"Jan", "Kersschot", []*Address{pa,wa}, "none"} - // fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}: + // fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}: // using an encoder: file, _ := os.OpenFile("vcard.gob", os.O_CREATE|os.O_WRONLY, 0) defer file.Close() @@ -125,16 +122,14 @@ func main() { log.Println("Error in encoding gob") } } - ``` **练习 12.8**:[degob.go](exercises/chapter_12/degob.go): 写一个程序读取 vcard.gob 文件,解码并打印它的内容。 - ## 链接 - [目录](directory.md) - 上一节:[XML 数据格式](12.10.md) -- 下一节:[Go 中的密码学](12.12.md) \ No newline at end of file +- 下一节:[Go 中的密码学](12.12.md) diff --git a/eBook/12.12.md b/eBook/12.12.md index 9efba3d..662f9e2 100644 --- a/eBook/12.12.md +++ b/eBook/12.12.md @@ -37,12 +37,14 @@ func main() { checksum := hasher.Sum(b) fmt.Printf("Result: %x\n", checksum) } -/* Output: +``` + +输出: + +``` Result: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 Result: [169 74 143 229 204 177 155 166 28 76 8 115 211 145 233 135 152 47 187 211] Result: e2222bfc59850bbb00a722e764a555603bb59b2a -*/ - ``` 通过调用 `sha1.New()` 创建了一个新的 `hash.Hash` 对象,用来计算 SHA1 校验值。`Hash` 类型实际上是一个接口,它实现了 `io.Writer` 接口: @@ -69,7 +71,6 @@ type Hash interface { // are a multiple of the block size. BlockSize() int } - ``` 通过 io.WriteString 或 hasher.Write 计算给定字符串的校验值。 @@ -78,7 +79,6 @@ type Hash interface { 在示例 12.20 中检验 md5 算法。 - ## 链接 - [目录](directory.md) diff --git a/eBook/12.7.md b/eBook/12.7.md index 5844f74..f70f518 100644 --- a/eBook/12.7.md +++ b/eBook/12.7.md @@ -9,10 +9,9 @@ func data(name string) string { contents := io.ReadAll(f) return contents } - ``` -在函数 return 后执行了 `f.Close()` +在函数 return 后执行了 `f.Close()` ## 链接 diff --git a/eBook/12.8.md b/eBook/12.8.md index f667ce3..06fd0b2 100644 --- a/eBook/12.8.md +++ b/eBook/12.8.md @@ -3,6 +3,7 @@ 例子程序 `io_interfaces.go` 很好的阐述了 io 包中的接口概念。 示例 12.15 [io_interfaces.go](examples/chapter_12/io_interfaces.go): + ```go // interfaces being used in the GO-package fmt package main @@ -22,7 +23,6 @@ func main() { fmt.Fprintf(buf, "%s\n", "hello world! - buffered") buf.Flush() } - ``` 输出: @@ -31,10 +31,11 @@ func main() { hello world! - unbuffered hello world! - buffered ``` + 下面是 `fmt.Fprintf()` 函数的实际签名 ```go -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) ``` 其不是写入一个文件,而是写入一个 `io.Writer` 接口类型的变量,下面是 `Writer` 接口在 io 包中的定义: @@ -43,7 +44,8 @@ type Writer interface { Write(p []byte) (n int, err error) } ``` -`fmt.Fprintf()` 依据指定的格式向第一个参数内写入字符串,第一参数必须实现了 `io.Writer` 接口。`Fprintf()` 能够写入任何类型,只要其实现了 `Write` 方法,包括 `os.Stdout`,文件(例如 os.File),管道,网络连接,通道等等,同样的也可以使用 bufio 包中缓冲写入。bufio 包中定义了 `type Writer struct{...}` + +`fmt.Fprintf()` 依据指定的格式向第一个参数内写入字符串,第一参数必须实现了 `io.Writer` 接口。`Fprintf()` 能够写入任何类型,只要其实现了 `Write` 方法,包括 `os.Stdout`,文件(例如 os.File),管道,网络连接,通道等等,同样的也可以使用 bufio 包中缓冲写入。bufio 包中定义了 `type Writer struct{...}`。 bufio.Writer 实现了 Write 方法: @@ -56,14 +58,15 @@ func (b *Writer) Write(p []byte) (nn int, err error) ```go func NewWriter(wr io.Writer) (b *Writer) ``` + 其适合任何形式的缓冲写入。 在缓冲写入的最后千万不要忘了使用 `Flush()`,否则最后的输出不会被写入。 在 15.2-15.8 章节,我们将使用 `fmt.Fprint` 函数向 `http.ResponseWriter` 写入,其同样实现了 io.Writer 接口。 - **练习 12.7**:[remove_3till5char.go](exercises/chapter_12/remove_3till5char.go) + 下面的代码有一个输入文件 `goprogram.go`,然后以每一行为单位读取,从读取的当前行中截取第 3 到第 5 的字节写入另一个文件。然而当你运行这个程序,输出的文件却是个空文件。找出程序逻辑中的 bug,修正它并测试。 ```go diff --git a/eBook/12.9.md b/eBook/12.9.md index 5991e8c..620e091 100644 --- a/eBook/12.9.md +++ b/eBook/12.9.md @@ -1,4 +1,4 @@ -# 12.9 Json 数据格式 +# 12.9 JSON 数据格式 数据结构要在网络中传输或保存到文件,就必须对其编码和解码;目前存在很多编码格式:JSON,XML,gob,Google 缓冲协议等等。Go 语言支持所有这些编码格式;在后面的章节,我们将讨论前三种格式。 @@ -34,7 +34,6 @@ Go 语言的 json 包可以让你在程序中方便的读取和写入 JSON 数 我们将在下面的例子里使用 json 包,并使用练习 10.1 vcard.go 中一个简化版本的 Address 和 VCard 结构(为了简单起见,我们忽略了很多错误处理,不过在实际应用中你必须要合理的处理这些错误,参阅 13 章) - 示例 12.16 [json.go](examples/chapter_12/json.go): ```go @@ -78,7 +77,6 @@ func main() { log.Println("Error in encoding json") } } - ``` `json.Marshal()` 的函数签名是 `func Marshal(v interface{}) ([]byte, error)`,下面是数据编码后的 JSON 文本(实际上是一个 []bytes): @@ -185,7 +183,7 @@ for k, v := range m { 通过这种方式,你可以处理未知的 JSON 数据,同时可以确保类型安全。 -### 解码数据到结构: +### 解码数据到结构 如果我们事先知道 JSON 数据,我们可以定义一个适当的结构并对 JSON 数据反序列化。下面的例子中,我们将定义: @@ -208,6 +206,7 @@ err := json.Unmarshal(b, &m) 程序实际上是分配了一个新的切片。这是一个典型的反序列化引用类型(指针、切片和 map)的例子。 ### 编码和解码流 + json 包提供 Decoder 和 Encoder 类型来支持常用 JSON 数据流读写。NewDecoder 和 NewEncoder 函数分别封装了 io.Reader 和 io.Writer 接口。 ```go diff --git a/eBook/directory.md b/eBook/directory.md index b8a8bcf..57b0dc8 100644 --- a/eBook/directory.md +++ b/eBook/directory.md @@ -120,7 +120,7 @@ - 12.6 [用切片读写文件](12.6.md) - 12.7 [用 defer 关闭文件](12.7.md) - 12.8 [使用接口的实际例子:fmt.Fprintf](12.8.md) - - 12.9 [格式化 Json 数据](12.9.md) + - 12.9 [格式化 JSON 数据](12.9.md) - 12.10 [XML 数据格式](12.10.md) - 12.11 [用 Gob 传输数据](12.11.md) - 12.12 [Go 中的密码学](12.12.md)