如何在 The Go Programming Language 中实施练习
How to implement a exercise in The Go Programming Language
练习 7.5:
io
包中的 LimitReader
函数接受一个 io.Reader
r
和多个字节 n
,以及 returns 另一个 Reader
从 r
读取但在 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))
}
看来您对需要做的事情的概念还不是很清楚。
您需要创建具有以下签名的函数:
func LimitReader(r io.Reader, n int64) io.Reader
也就是传了一个r
io.Reader
和一个n
号,你要return一个新的io.Reader
。当有人从returnedreader读取数据时,读取的数据必须来自传递的r
reader,并且应该自动计算读取的字节数;并且如果读取的字节超过 n
数量,则它 不得 从 r
而是 return io.EOF
中读取更多字节以指示已到达流的末尾。可能是 r
reader 有更多字节(意味着可以从中读取更多字节),但不应读取和 returned:这就是 [= 的目的26=].
如果您认为自己现在理解了问题,请暂时停止阅读答案,并尝试自己实施。以下是示例解决方案。
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} }
它return是一个*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
是一个结构体,它包含它读取的 source reader,以及仍然可以读取的字节数,而无需报告 io.EOF
。所以 LimitReader()
只是 return 这个结构的一个值,其中参数 r
和 n
被分配给字段 R
和 N
结构。更具体地说,这个结构的地址是 returned,因为 LimitedReader.Read()
有指针接收器,所以只有指向它的指针实现 io.Reader
。它有一个指针接收器,因为 Read()
方法(可能)修改结构的字段,所以需要一个指针才能做到这一点(否则只会修改一个副本,在 Read()
方法returns).
LimitedReader.Read()
首先检查 N
字段,它告诉我们还可以 return 多少字节,如果没有更多 "allowed",则表现良好Limited-reader,它 returns io.EOF
立即没有从源中读取更多字节:
if l.N <= 0 {
return 0, EOF
}
如果N
为正数,这意味着一些字节可以被读取和return编辑,但不超过N
,所以如果传递给 Read()
的 p
切片有更长的长度,我们 重新切片 它所以调用源 reader 将不会读取更多超过我们应该允许的:
if int64(len(p)) > l.N {
p = p[0:l.N]
}
而最后一部分只不过是实际阅读,来源reader:
n, err = l.R.Read(p)
其中return实际读取的字节数,以及一个可选的错误(读取是否遇到错误)。因为我们要 return 这些,所以我们必须管理现在 returned 的字节数,我们必须从允许的剩余字节中减去它:
l.N -= int64(n)
return
练习 7.5:
io
包中的 LimitReader
函数接受一个 io.Reader
r
和多个字节 n
,以及 returns 另一个 Reader
从 r
读取但在 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))
}
看来您对需要做的事情的概念还不是很清楚。
您需要创建具有以下签名的函数:
func LimitReader(r io.Reader, n int64) io.Reader
也就是传了一个r
io.Reader
和一个n
号,你要return一个新的io.Reader
。当有人从returnedreader读取数据时,读取的数据必须来自传递的r
reader,并且应该自动计算读取的字节数;并且如果读取的字节超过 n
数量,则它 不得 从 r
而是 return io.EOF
中读取更多字节以指示已到达流的末尾。可能是 r
reader 有更多字节(意味着可以从中读取更多字节),但不应读取和 returned:这就是 [= 的目的26=].
如果您认为自己现在理解了问题,请暂时停止阅读答案,并尝试自己实施。以下是示例解决方案。
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} }
它return是一个*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
是一个结构体,它包含它读取的 source reader,以及仍然可以读取的字节数,而无需报告 io.EOF
。所以 LimitReader()
只是 return 这个结构的一个值,其中参数 r
和 n
被分配给字段 R
和 N
结构。更具体地说,这个结构的地址是 returned,因为 LimitedReader.Read()
有指针接收器,所以只有指向它的指针实现 io.Reader
。它有一个指针接收器,因为 Read()
方法(可能)修改结构的字段,所以需要一个指针才能做到这一点(否则只会修改一个副本,在 Read()
方法returns).
LimitedReader.Read()
首先检查 N
字段,它告诉我们还可以 return 多少字节,如果没有更多 "allowed",则表现良好Limited-reader,它 returns io.EOF
立即没有从源中读取更多字节:
if l.N <= 0 {
return 0, EOF
}
如果N
为正数,这意味着一些字节可以被读取和return编辑,但不超过N
,所以如果传递给 Read()
的 p
切片有更长的长度,我们 重新切片 它所以调用源 reader 将不会读取更多超过我们应该允许的:
if int64(len(p)) > l.N {
p = p[0:l.N]
}
而最后一部分只不过是实际阅读,来源reader:
n, err = l.R.Read(p)
其中return实际读取的字节数,以及一个可选的错误(读取是否遇到错误)。因为我们要 return 这些,所以我们必须管理现在 returned 的字节数,我们必须从允许的剩余字节中减去它:
l.N -= int64(n)
return