duangouhui0446 2016-10-11 00:43
浏览 13
已采纳

如何使用Go编程语言进行练习

Exercise 7.5:
The LimitReader function in the io package accepts an io.Reader r and a number of bytes n, and returns another Reader that reads from r but reports an end-of-file condition after n bytes. Implement it.

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

How to implement it?


Below is my code, I know it not right.

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
" , 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条回答 默认 最新

  • drtj40036 2016-10-11 07:03
    关注

    It seems you are not clear with the concepts of what you need to do.

    You need to create a function with the following signature:

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

    That is, an r io.Reader and an n number is passed to it, and you have to return a new io.Reader. When someone reads from the returned reader, the read data must come from the passed r reader, and it should automatically count the read bytes; and if the read bytes exceeds the n number, it must not read further bytes from r but return io.EOF which is used to indicate that the end of the stream is reached. It could be that the r reader has more bytes (meaning more bytes could be read from it), but that should not be read and returned: that's the purpose of the LimitedReader.

    If you think you understand the problem now, stop reading the answer for now, and try to implement this yourself. What follows is an example solution.


    This exact functionality already exists in the io package, and goes by the same name: 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} }
    

    It returns a value of *io.LimitedReader, whose implementation is this:

    // 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
    }
    

    Take a minute or 2 to try to understand the code yourself. If you're stuck or not everything is clear, read on.

    Explaining the code:

    io.LimitedReader is a struct, which contains the source reader it reads from, and the number of bytes that can still be read without having to report io.EOF. So LimitReader() simply just returns a value of this struct where the parameters r and n are assigned to the fields R and N of the struct. More specifically an address of this struct is returned, because LimitedReader.Read() has pointer receiver, and so only a pointer to it implements io.Reader. And it has a pointer receiver, because the Read() method (may) modify the fields of the struct, so a pointer is required to be able to do that (else only a copy would be modified which is discarded after the Read() method returns).

    LimitedReader.Read() first checks the N field which tells how many more bytes can we return, and if there is no more "allowed", being a well-behaved Limited-reader, it returns io.EOF immedately without reading any more bytes from the source:

    if l.N <= 0 {
        return 0, EOF
    }
    

    If N is positive, that means some bytes may be read and returned, but no more than N, so if the p slice passed to Read() has a greater length, we re-slice it so a call to the source reader will not read more than what we should allow:

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

    And the last part is nothing more that actually doing the reading, from the source reader:

    n, err = l.R.Read(p)
    

    Which returns the number of actually read bytes, and an optional error (whether reading encountered some error). Since we're about to return these, we have to administer that this amount of bytes are now returned, we have to subtract this from the allowed remaining bytes:

    l.N -= int64(n)
    return
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法