课程理解&疑问
来源:7-2 函数式编程例一

merlin丶kael
2022-04-13
以下是我对这节课的理解
- intGen实现了Read接口, 所以可以当参数 调printFileContent(reader),
- 当执行 scanner.Scan() 方法时, 会调用 io.Reader.Read()方法, 也就是
- intGen自己实现的Read方法, 然后会执行fibonacci() 获取 一个斐波那契数列 元素, 也就是
- scanner.Scan() 方法的返回值.
- 进入下一个 循环, 一直调用fibonacci()
我的疑问是:
p []byte 数组可能会太小, 但是 调用fibonacci() 获取 斐波那契数列 元素 的逻辑 应该是正确的, 只是 Read函数输出的 值是错误的,
下面这个代码 没看明白
package main
import (
"fmt"
"io"
"strings"
)
// 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
func Fibonacci() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}
type intGen2 struct {
gen func() int
currentReader io.Reader
}
func (g *intGen2) Read(
p []byte) (n int, err error) {
err = io.EOF
if g.currentReader != nil {
n, err = g.currentReader.Read(p)
}
if err == io.EOF {
next := g.gen()
s := fmt.Sprintf("%d\n", next)
g.currentReader = strings.NewReader(s)
if n == 0 {
n, err = g.currentReader.Read(p)
}
}
return n, err
}
func main() {
f := &intGen2{
gen: Fibonacci(),
}
for i := 0; i < 20; i++ {
b := make([]byte, 1)
n, err := f.Read(b)
fmt.Printf("%d bytes read: %q. err = %v\n", n, b, err)
}
}
写回答
1回答
-
这个代码是我修正所谓p []byte太小的问题。加了一个currentReader来记录当前用来读取数据的Reader。
next := g.gen() s := fmt.Sprintf("%d\n", next) g.currentReader = strings.NewReader(s)
这几行就是把数据读取到一个字符串s,再通过字符串s构造一个Reader,可以用于通过Reader接口读取这个s。
那么我们的问题就变成何时通过上面几行来生成下一个currentReader。答案就是上一个currentReader读取完毕。
所以我们有if err == io.EOF,来指明上一个currentReader读取完毕。
然后还有一个细节,我们只要有currentReader,就从currentReader读取。只要读取的结果(或者没有读取过)是EOF,我们就生成下一个currentReader。但是有一种可能是从currentReader里什么都没读到,直接报了EOF,那么我们也应该从下一个生成的currentReader里来读取,保证我们的Read方法总能读到东西。这就是后面又有一个判断说if n == 0
112022-05-10
相似问题