如何在Go编程语言中实现练习

时间:2016-10-11 00:43:11

标签: go bytestream

练习7.5:
LimitReader包中的io函数接受io.Reader r和多个字节n,并返回从Reader读取的另一个r {1}}但报告n字节后的文件结束条件。实施它。

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

如何实施?

以下是我的代码,我知道它不对。

type MyReader struct {
    bytes []byte
    length int
}

func (myReader *MyReader) Read (p []byte) (int, error) {
    fmt.Println("be invoked")
    myReader.bytes = p
    myReader.length = len(p)
    fmt.Printf("lenght: %d\n" , myReader.length)
    return len(p), nil
}
func LimitReader(r io.Reader, n int64) io.Reader {
    filecontent, _:= ioutil.ReadFile("./testfile.txt")
    r.Read(filecontent[:n])
    return r
}

func main() {
    myReader := &MyReader{}
    r := LimitReader(myReader, 100)
    filecontent, _:= ioutil.ReadFile("./testfile.txt")
    fmt.Println(r.Read(filecontent))
}

1 个答案:

答案 0 :(得分:2)

您似乎并不清楚自己需要做什么的概念。

您需要使用以下签名创建一个函数:

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

也就是说,r io.Readern号码会传递给它,您必须返回新的io.Reader。当有人从返回的读取器中读取数据时,读取的数据必须来自传递的r读取器,它应自动计算读取的字节数;如果读取的字节数超过n,则不得r读取更多字节,但返回io.EOF,用于表示结束到达流。可能是r读者有更多字节(意味着可以从中读取更多字节),但不应该读取和返回:这是LimitedReader的目的。

如果您认为自己现在明白这个问题,请暂时停止阅读答案,并尝试自己实现。以下是一个示例解决方案。

这个确切的功能已存在于io包中,并使用相同的名称:io.LimitReader()

// LimitReader returns a Reader that reads from r
// but stops with EOF after n bytes.
// The underlying implementation is a *LimitedReader.
func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }

返回值*io.LimitedReader,其实现如下:

// A LimitedReader reads from R but limits the amount of
// data returned to just N bytes. Each call to Read
// updates N to reflect the new amount remaining.
type LimitedReader struct {
    R Reader // underlying reader
    N int64  // max bytes remaining
}

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

花一两分钟时间尝试自己理解代码。如果您遇到困难或一切都很清楚,请继续阅读。

解释代码:

io.LimitedReader是一个结构,它包含从中读取的读取器,以及无需报告io.EOF即可读取的字节数。因此,LimitReader()只返回此结构的值,其中参数rn被分配给结构的字段RN。更具体地说,返回此结构的地址,因为LimitedReader.Read()具有指针接收器,因此只有指向它的指针实现io.Reader。它有一个指针接收器,因为Read()方法(可能)修改结构的字段,因此需要指针才能这样做(否则只修改一个副本,在{之后丢弃) {1}}方法返回)。

Read()首先检查LimitedReader.Read()字段,该字段告诉我们可以返回多少字节,如果没有“允许”字段,作为一个表现良好的限制读取器,它将返回{{ 1}}在没有从源中读取任何更多字节的情况下:

N

如果io.EOF为正,则表示可以读取并返回某些字节,但不超过if l.N <= 0 { return 0, EOF } ,因此如果N切片传递给N的长度更长,我们重新切片,因此对源阅读器的调用不会超出我们应该允许的范围:

p

最后一部分实际上是从源读者那里读取的:

Read()

返回实际读取的字节数和可选错误(读取是否遇到某些错误)。由于我们即将返回这些,我们必须管理现在返回的这个字节数,我们必须从允许的剩余字节中减去它:

if int64(len(p)) > l.N {
    p = p[0:l.N]
}