mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-12 03:34:15 +08:00
修正发现的13章以前的一些小问题 (#277)
* Update 07.3.md * Update 07.3.md * Update 07.6.md * fix few problems * Update 10.6 and 10.8 * Update 11.6 and 11.7 * fix some problems before Chap13 * add a dot
This commit is contained in:
@@ -54,7 +54,7 @@ const (
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
对于变量 x,如果 `v:=reflect.ValueOf(x)`,那么 `v.Kind()` 返回 float64 ,所以下面的表达式是 `true`
|
对于 float64 类型的变量 x,如果 `v:=reflect.ValueOf(x)`,那么 `v.Kind()` 返回 `reflect.Float64` ,所以下面的表达式是 `true`
|
||||||
`v.Kind() == reflect.Float64`
|
`v.Kind() == reflect.Float64`
|
||||||
|
|
||||||
Kind 总是返回底层类型:
|
Kind 总是返回底层类型:
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 11.12.1 Go 的动态类型
|
## 11.12.1 Go 的动态类型
|
||||||
|
|
||||||
在经典的面向对象语言(像 C++,Java 和 C#)中数据和方法被封装为 `类的概念`:类包含它们两者,并且不能剥离。
|
在经典的面向对象语言(像 C++,Java 和 C#)中数据和方法被封装为 `类` 的概念:类包含它们两者,并且不能剥离。
|
||||||
|
|
||||||
Go 没有类:数据(结构体或更一般的类型)和方法是一种松耦合的正交关系。
|
Go 没有类:数据(结构体或更一般的类型)和方法是一种松耦合的正交关系。
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ Go 中的接口跟 Java/C# 类似:都是必须提供一个指定方法集的
|
|||||||
|
|
||||||
和其它语言相比,Go 是唯一结合了接口值,静态类型检查(是否该类型实现了某个接口),运行时动态转换的语言,并且不需要显式地声明类型是否满足某个接口。该特性允许我们在不改变已有的代码的情况下定义和使用新接口。
|
和其它语言相比,Go 是唯一结合了接口值,静态类型检查(是否该类型实现了某个接口),运行时动态转换的语言,并且不需要显式地声明类型是否满足某个接口。该特性允许我们在不改变已有的代码的情况下定义和使用新接口。
|
||||||
|
|
||||||
接收一个(或多个)接口类型作为参数的函数,可以被实现了该接口的类型实例调用。`实现了某个接口的类型可以被传给任何以此接口为参数的函数`。
|
接收一个(或多个)接口类型作为参数的函数,其实参可以是任何实现了该接口的类型。 `实现了某个接口的类型可以被传给任何以此接口为参数的函数` 。
|
||||||
|
|
||||||
类似于 Python 和 Ruby 这类动态语言中的 `动态类型(duck typing)`;这意味着对象可以根据提供的方法被处理(例如,作为参数传递给函数),而忽略它们的实际类型:它们能做什么比它们是什么更重要。
|
类似于 Python 和 Ruby 这类动态语言中的 `动态类型(duck typing)`;这意味着对象可以根据提供的方法被处理(例如,作为参数传递给函数),而忽略它们的实际类型:它们能做什么比它们是什么更重要。
|
||||||
|
|
||||||
|
@@ -98,7 +98,7 @@ allUnsortedCars.Process(sortedAppender)
|
|||||||
BMWCount := len(sortedCars[“BMW”])
|
BMWCount := len(sortedCars[“BMW”])
|
||||||
```
|
```
|
||||||
|
|
||||||
我们让这些代码在下面的程序 cars.go(此处只展示了 main() 中的代码,别的代码已经在上面展示)中执行:
|
我们让这些代码在下面的程序 cars.go 中执行:
|
||||||
|
|
||||||
示例 11.18 [cars.go](examples/chapter_11/cars.go):
|
示例 11.18 [cars.go](examples/chapter_11/cars.go):
|
||||||
|
|
||||||
|
@@ -73,7 +73,7 @@ type Hash interface {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
通过 io.WriteString 或 hasher.Write 计算给定字符串的校验值。
|
通过 io.WriteString 或 hasher.Write 将给定的 []byte 附加到当前的 `hash.Hash` 对象中。
|
||||||
|
|
||||||
**练习 12.9**:[hash_md5.go](exercises/chapter_12/hash_md5.go):
|
**练习 12.9**:[hash_md5.go](exercises/chapter_12/hash_md5.go):
|
||||||
|
|
||||||
|
@@ -67,7 +67,7 @@ func NewWriter(wr io.Writer) (b *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`,然后以每一行为单位读取,从读取的当前行中截取第 3 到第 5 的字节写入另一个文件。然而当你运行这个程序,输出的文件却是个空文件。找出程序逻辑中的 bug,修正它并测试。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@@ -76,11 +76,12 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
inputFile, _ := os.Open("goprogram.go")
|
inputFile, _ := os.Open("goprogram")
|
||||||
outputFile, _ := os.OpenFile("goprogramT.go", os.O_WRONLY|os.O_CREATE, 0666)
|
outputFile, _ := os.OpenFile("goprogramT", os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
defer inputFile.Close()
|
defer inputFile.Close()
|
||||||
defer outputFile.Close()
|
defer outputFile.Close()
|
||||||
inputReader := bufio.NewReader(inputFile)
|
inputReader := bufio.NewReader(inputFile)
|
||||||
@@ -91,7 +92,7 @@ func main() {
|
|||||||
fmt.Println("EOF")
|
fmt.Println("EOF")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
outputString := string([]byte(inputString)[2:5]) + "\r\n"
|
outputString := string(inputString[2:5]) + "\r\n"
|
||||||
n, err := outputWriter.WriteString(outputString)
|
n, err := outputWriter.WriteString(outputString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@@ -28,16 +28,16 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
尽管 XML 被广泛的应用,但是 JSON 更加简洁、轻量(占用更少的内存、磁盘及网络带宽)和更好的可读性,这也说明它越来越受欢迎。
|
尽管 XML 被广泛的应用,但是 JSON 更加简洁、轻量(占用更少的内存、磁盘及网络带宽)和更好的可读性,这也使它越来越受欢迎。
|
||||||
|
|
||||||
Go 语言的 json 包可以让你在程序中方便的读取和写入 JSON 数据。
|
Go 语言的 json 包可以让你在程序中方便的读取和写入 JSON 数据。
|
||||||
|
|
||||||
我们将在下面的例子里使用 json 包,并使用练习 10.1 vcard.go 中一个简化版本的 Address 和 VCard 结构(为了简单起见,我们忽略了很多错误处理,不过在实际应用中你必须要合理的处理这些错误,参阅 13 章)
|
我们将在下面的例子里使用 json 包,并使用练习 10.1 [vcard.go](exercises/chapter_10/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
|
||||||
// json.go.go
|
// json.go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -79,7 +79,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`json.Marshal()` 的函数签名是 `func Marshal(v interface{}) ([]byte, error)`,下面是数据编码后的 JSON 文本(实际上是一个 []bytes):
|
`json.Marshal()` 的函数签名是 `func Marshal(v interface{}) ([]byte, error)`,下面是数据编码后的 JSON 文本(实际上是一个 []byte):
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
{
|
{
|
||||||
@@ -100,6 +100,8 @@ func main() {
|
|||||||
|
|
||||||
出于安全考虑,在 web 应用中最好使用 `json.MarshalforHTML()` 函数,其对数据执行HTML转码,所以文本可以被安全地嵌在 HTML `<script>` 标签中。
|
出于安全考虑,在 web 应用中最好使用 `json.MarshalforHTML()` 函数,其对数据执行HTML转码,所以文本可以被安全地嵌在 HTML `<script>` 标签中。
|
||||||
|
|
||||||
|
`json.NewEncoder()` 的函数签名是 `func NewEncoder(w io.Writer) *Encoder`,返回的Encoder类型的指针可调用方法 `Encode(v interface{})`,将数据对象 v 的json编码写入 `io.Writer` w 中。
|
||||||
|
|
||||||
JSON 与 Go 类型对应如下:
|
JSON 与 Go 类型对应如下:
|
||||||
|
|
||||||
- bool 对应 JSON 的 booleans
|
- bool 对应 JSON 的 booleans
|
||||||
@@ -118,11 +120,11 @@ JSON 与 Go 类型对应如下:
|
|||||||
|
|
||||||
`UnMarshal()` 的函数签名是 `func Unmarshal(data []byte, v interface{}) error` 把 JSON 解码为数据结构。
|
`UnMarshal()` 的函数签名是 `func Unmarshal(data []byte, v interface{}) error` 把 JSON 解码为数据结构。
|
||||||
|
|
||||||
我们首先创建一个结构 Message 用来保存解码的数据:`var m Message` 并调用 `Unmarshal()`,解析 []byte 中的 JSON 数据并将结果存入指针 m 指向的值
|
示例12.16中对 vc 编码后的数据为 `js` ,对其解码时,我们首先创建结构 VCard 用来保存解码的数据:`var v VCard` 并调用 `json.Unmarshal(js, &v)`,解析 []byte 中的 JSON 数据并将结果存入指针 &v 指向的值。
|
||||||
|
|
||||||
虽然反射能够让 JSON 字段去尝试匹配目标结构字段;但是只有真正匹配上的字段才会填充数据。字段没有匹配不会报错,而是直接忽略掉。
|
虽然反射能够让 JSON 字段去尝试匹配目标结构字段;但是只有真正匹配上的字段才会填充数据。字段没有匹配不会报错,而是直接忽略掉。
|
||||||
|
|
||||||
(练习 15.2b twitter_status_json.go 中用到了 UnMarshal)
|
(练习 15.2b [twitter_status_json.go](exercises/chapter_15/twitter_status_json.go) 中用到了 UnMarshal)
|
||||||
|
|
||||||
### 解码任意的数据:
|
### 解码任意的数据:
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// json.go.go
|
// json.go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
Reference in New Issue
Block a user