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