mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-12-19 20:24:20 +08:00
Compare commits
6 Commits
9e504959ee
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ecbba5baa | ||
|
|
522457fa25 | ||
|
|
c58743acce | ||
|
|
cc738922ed | ||
|
|
c080b2ac6d | ||
|
|
1ed9861965 |
@@ -119,7 +119,7 @@ $ ./outline2 http://gopl.io
|
||||
|
||||
**练习 5.7:** 完善startElement和endElement函数,使其成为通用的HTML输出器。要求:输出注释结点,文本结点以及每个元素的属性(< a href='...'>)。使用简略格式输出没有孩子结点的元素(即用`<img/>`代替`<img></img>`)。编写测试,验证程序输出的格式正确。(详见11章)
|
||||
|
||||
**练习 5.8:** 修改pre和post函数,使其返回布尔类型的返回值。返回false时,中止forEachNoded的遍历。使用修改后的代码编写ElementByID函数,根据用户输入的id查找第一个拥有该id元素的HTML元素,查找成功后,停止遍历。
|
||||
**练习 5.8:** 修改pre和post函数,使其返回布尔类型的返回值。返回false时,中止forEachNode的遍历。使用修改后的代码编写ElementByID函数,根据用户输入的id查找第一个拥有该id元素的HTML元素,查找成功后,停止遍历。
|
||||
|
||||
```Go
|
||||
func ElementByID(doc *html.Node, id string) *html.Node
|
||||
@@ -130,3 +130,4 @@ func ElementByID(doc *html.Node, id string) *html.Node
|
||||
```Go
|
||||
func expand(s string, f func(string) string) string
|
||||
```
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ any = new(bytes.Buffer)
|
||||
|
||||
对于创建的一个interface{}值持有一个boolean,float,string,map,pointer,或者任意其它的类型;我们当然不能直接对它持有的值做操作,因为interface{}没有任何方法。我们会在7.10章中学到一种用类型断言来获取interface{}中值的方法。
|
||||
|
||||
因为接口与实现只依赖于判断两个类型的方法,所以没有必要定义一个具体类型和它实现的接口之间的关系。也就是说,有意地在文档里说明或者程序上断言这种关系偶尔是有用的,但程序上不强制这么做。下面的定义在编译期断言一个`*bytes.Buffer`的值实现了io.Writer接口类型:
|
||||
因为接口与实现只依赖于判断两个类型的方法,所以没有必要定义一个具体类型和它实现的接口之间的关系。也就是说,有意地在文档里说明或者程序上断言这种关系偶尔是有用的,但程序上不强制这么做。这种写法还可用于让编译器在编译期确保某个类型确实满足接口要求,从而提前发现实现遗漏或接口变更导致的不匹配问题。下面的定义在编译期断言一个`*bytes.Buffer`的值实现了io.Writer接口类型:
|
||||
|
||||
```go
|
||||
// *bytes.Buffer must satisfy io.Writer
|
||||
@@ -150,3 +150,4 @@ type Streamer interface {
|
||||
```
|
||||
|
||||
每一个具体类型的组基于它们相同的行为可以表示成一个接口类型。不像基于类的语言,他们一个类实现的接口集合需要进行显式的定义,在Go语言中我们可以在需要的时候定义一个新的抽象或者特定特点的组,而不需要修改具体类型的定义。当具体的类型来自不同的作者时这种方式会特别有用。当然也确实没有必要在具体的类型中指出这些共性。
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ if out != nil {
|
||||
|
||||
动态分配机制依然决定(\*bytes.Buffer).Write的方法会被调用,但是这次的接收者的值是nil。对于一些如\*os.File的类型,nil是一个有效的接收者(§6.2.1),但是\*bytes.Buffer类型不在这些种类中。这个方法会被调用,但是当它尝试去获取缓冲区时会发生panic。
|
||||
|
||||
问题在于尽管一个nil的\*bytes.Buffer指针有实现这个接口的方法,它也不满足这个接口具体的行为上的要求。特别是这个调用违反了(\*bytes.Buffer).Write方法的接收者非空的隐含先觉条件,所以将nil指针赋给这个接口是错误的。解决方案就是将main函数中的变量buf的类型改为io.Writer,因此可以避免一开始就将一个不完整的值赋值给这个接口:
|
||||
问题在于尽管一个nil的\*bytes.Buffer指针有实现这个接口的方法,它也不满足这个接口具体的行为上的要求。特别是这个调用违反了(\*bytes.Buffer).Write方法的接收者非空的隐含先决条件,所以将nil指针赋给这个接口是错误的。解决方案就是将main函数中的变量buf的类型改为io.Writer,因此可以避免一开始就将一个不完整的值赋值给这个接口:
|
||||
|
||||
```go
|
||||
var buf io.Writer
|
||||
@@ -162,3 +162,4 @@ f(buf) // OK
|
||||
```
|
||||
|
||||
现在我们已经把接口值的技巧都讲完了,让我们来看更多的一些在Go标准库中的重要接口类型。在下面的三章中,我们会看到接口类型是怎样用在排序,web服务,错误处理中的。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user