斐波那契的问题

来源:1-1 接口的概念

宝慕林5317199

2021-06-23 20:10:46

func(g intGen) Read(p []byte)

老师说这个p可能太小,导致读的时候有问题,又说解决方案不在这个课上讲了。我百思不得其解,希望老师能否给个解决方案?


我自己打断点debug,这个p的大小是系统给初始化的,每次默认长度和容量都是4096。 完全不懂老师讲的太小啥意思?如何控制大小,什么时候会出现太小导致报错?

写回答

1回答

ccmouse

2021-06-24

同学已经研究的很深入了,找到了这个默认长度4096。是这样的,使用Scanner不会有问题。但是我们这里的Read函数必须针对所有的参数都适用,而不是仅能配合Scanner使用。

我们强行分配一个大小为1的缓冲区:

buf := make([]byte, 1)

g.Read(buf)

这样就可以使它出错。


解决的方法比较直接,我们把intGen类型做成一个struct而不是函数,用currentReader来保存读了一半的数:

type intGen struct {

  gen func() int

  currentReader io.Reader

}

在func(g *intGen) Read(p []byte)中,我们:

  1. currentReader存了之前读了一半的数据,首先尝试从currentReader读取数据。

  2. 若读到了EOF,说明之前的数据读完,我们就要调用gen()函数生成下一个数,并生成新的currentReader

  3. 如果步骤1中没有读到任何数据就直接返回了EOF,那么从新的currentReader再次尝试读取。(反之有可能读到了一个尾巴,并且读到EOF,这样我们不需要再次读取)


完整代码:

type intGen struct {

    gen           func() int

    currentReader io.Reader

}


func (g *intGen) 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", next)

        g.currentReader = strings.NewReader(s)

        if n == 0 {

            n, err = g.currentReader.Read(p)

        }

    }

    return n, err

}

Go playground运行结果:https://play.studygolang.com/p/gQKQtbHKfRL

0
hcmouse
hp>我自己也写了一段彻底解决这个问题的代码,并修改了一下我之前的文字描述。

h021-06-27
共4条回复

0 学习 · 1399 问题

查看课程