96

Go程序设计语言课后习题答案-第七章(接口)

 5 years ago
source link: https://www.zoulei.net/2018/06/24/the_go_programming_lang_usage_answer_7/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
  • 接口即约定
  • 接口类型
  • 实现接口
  • 使用flag.Value来解析参数
  • 接口值
  • 使用Sort.Interface来排序
  • http.Handler接口
  • error接口
  • 示例: 表达式求值器
  • 类型断言
  • 使用类型断言来识别错误
  • 通过接口类型断言来查询特性
  • 类型分支
  • 示例: 基于标记的XML解析
  • 一些建议

这章是重点

练习7.1:

使用类似ByteCounter的想法,实现单词和行的计数器.实现时考虑使用bufio.ScanWords

  • 创建一个结构体,实现Writer方法,分词得到写入的个数
package main

import (
	"fmt"
	"bufio"
	"strings"
)

type ByteCounter int

func (c *ByteCounter)Write(p []byte)(int, error) {
	scan := bufio.NewScanner(strings.NewReader(string(p)))
	scan.Split(bufio.ScanWords)

	for scan.Scan() {
		*c += 1
	}
	return len(p), nil
}

func main() {
	var c ByteCounter

	var name = "Dolly"
	fmt.Fprintf(&c, "hello, %s", name)
	fmt.Println(c)
}

练习7.2:

实现一个满足如下前面的CountingWriter函数,输入一个io.Writer,输出一个封装了输入值的新Writer,以及一个指向int64的指针,该指针对应的值是新的Writer写入的字节数

func CountingWriter(w io.Writer) (io.Writer, *int64)

  • 这个地方使用了一个全局的变量统计写入的字节数,CountingWriter好像再外面封装了一层一样,仅仅只是为了记一个数,需要新建一个类型,然后让这个类型满足接口
package main

import "io"

var position int64

type Counting struct {
	W io.Writer
}

func (c *Counting)Write(p []byte)(nint, err error) {
	n, err = c.W.Write(p)
	position += int64(n)
	return n, err
}

func CountingWriter(w io.Writer)(io.Writer, *int64) {
	return &Counting{w}, &position
}

练习7.3:

为gopl.io/ch4/treesort中的*tree类型写一个String方法,用于展示其中的值序列

  • 这个练习题比较直白了,估计是想说类型可以自己添加方法,这个地方直接使用广度优先保存下了列表然后打印一下
func (t *tree)String()string {
	var deque []*tree
	var ret []int
	deque = append(deque, t)
	for len(deque) > 0 {
		current := deque[0]
		deque = deque[1:]
		if current.left != nil {
			deque = append(deque, current.left)
		}
		if current.right != nil {
			deque = append(deque, current.right)
		}
		ret = append(ret, current.value)
	}

	var buf bytes.Buffer
	buf.Write([]byte("{"))
	for i, v := range ret {
		if i == len(ret)-1 {
			buf.Write([]byte(fmt.Sprintf("%d", v)))
		} else {
			buf.Write([]byte(fmt.Sprintf("%d, ", v)))
		}
	}
	buf.Write([]byte("}"))
	return buf.String()
}

练习7.4:

strings.NewReader函数输入一个字符串,返回一个从字符串读取数据并满足io.Reader接口的值.请自己实现该函数,并且通过它来让HTML分析器支持以字符串作为输入

  • Golang里面使用Newxxx这样的函数特别普遍,一个常用的套路,它初始化了一个struct,然后该结构体满足某接口
package main

import (
	"io"
	"io/ioutil"
	"fmt"
)

type S struct {
	R       string
	current int
}

func (s *S)Read(p []byte)(nint, err error) {
	if s.current >= len(s.R) {
		return 0, io.EOF
	}
	l := copy(p, s.R[s.current:])
	s.current = l
	return l, nil
}

func NewReader(sstring)io.Reader {
	return &S{s, 0}
}


func main() {
	r := NewReader("123")
	s, err := ioutil.ReadAll(r)
	if err != nil {
		fmt.Println(s)
	}
	fmt.Println(string(s))
}

练习7.5:

io包中的LimitReader函数接受io.Reader r和字节数n,返回一个Reader,该返回值从r读取数据,但在读取n字节后报告文件结束.请实现该函数

func LimitReader(r io.Reader,n int64) io.Reader

  • 感觉和上面的New差不多,只不过这个地方的初始化是使用了一个接口类型值
package main

import "io"

type LimitR struct {
	R io.Reader
	N int64
}

func (l *LimitR)Read(p []byte)(nint, err error) {
	if l.N <= 0 {
		return 0, io.EOF
	}
	if int64(len(p)) > l.N {
		p = p[0:l.N]
	}
	n, err = l.R.Read(p)
	l.N -= int64(n)
	return n, err
}

func LimitReader(r io.Reader, nint64)io.Reader {
	return &LimitR{r, n}
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK