为了账号安全,请及时绑定邮箱和手机立即绑定

Golang ioutil.ReadAll 无限循环

Golang ioutil.ReadAll 无限循环

Go
尚方宝剑之说 2022-06-01 16:21:24
我是 Golang 的新手。我试图了解如何使用 ioutil.ReadAll (非 HTTP 响应)。根据源代码(和文档):// ReadAll reads from r until an error or EOF and returns the data it read.// A successful call returns err == nil, not err == EOF. Because ReadAll is// defined to read from src until EOF, it does not treat an EOF from Read// as an error to be reported.func ReadAll(r io.Reader) ([]byte, error) {    return readAll(r, bytes.MinRead)}我在这个例子中实现了一个 io.Reader (也在Go Playground 上):// go version go1.13.5 darwin/amd64package mainimport (    "bytes"    "fmt"    "io/ioutil")// Thing contains a bodytype Thing struct {    Body []byte}// Read reads from body into pfunc (t Thing) Read(dst []byte) (n int, err error) {    // Note: bytes.Reader does return io.EOF    // https://golang.org/src/bytes/reader.go?s=1154:1204#L30    reader := bytes.NewReader(t.Body)    return reader.Read(dst)}func main() {    fmt.Println("Testing bytes")    thing := new(Thing)    thing.Body = []byte("Hello World")    fmt.Println("thing.Body:", string(thing.Body))    // This works    buf := make([]byte, len(thing.Body))    n, err := thing.Read(buf)    fmt.Println("Amount read:", n)    if err != nil {        fmt.Println("Error: ", err)    }    fmt.Println("buf:", string(buf))    // ReadAll runs forever....why?    buf2, err := ioutil.ReadAll(thing)    if err != nil {        fmt.Println("Error:", err)    }    fmt.Println("buf2:", buf2)}上面,读取实现工作正常。它只是调用 bytes.NewReader() 并从中读取。但是,在结构上使用 ioutil.ReadAll 时,它会永远运行(超时),我不明白为什么。最初我认为那里可能没有 EOF,但是字节阅读器源代码确实在此处返回 io.EOF:// Read implements the io.Reader interface.func (r *Reader) Read(b []byte) (n int, err error) {    if r.i >= int64(len(r.s)) {        return 0, io.EOF    }    r.prevRune = -1    n = copy(b, r.s[r.i:])    r.i += int64(n)    return}我已经在 http 响应主体上看到了其他实现,他们在阅读主体后明确地必须关闭主体,但我没有看到字节阅读器上的任何方法来关闭它。有人可以帮助我了解在这种情况下发生了什么吗?提前致谢。
查看完整描述

1 回答

?
潇湘沐

TA贡献1816条经验 获得超6个赞

bytes.Reader每次Thing.Read()调用时,您都在创建一个新的。每次获得相同的 11 个字节时,ReadAll()都会继续调用您的函数。Thing.Read()


根据您的评论,我认为您只想创建一次,例如,在“构造函数”中,您不需要存储Body它,因为它存储在Bytes.Reader.


type Thing struct {

    r io.Reader

}


func NewThing(s string) (t Thing) {

    t.r = bytes.NewReader([]byte(s))

    return

}


func (t Thing) Read(dst []byte) (n int, err error) {

    return t.r.Read(dst)

}

但那Thing只是一个io.Reader没有目的的包装。你也可以直接使用`io.Reader'。


    buf2, err := ioutil.ReadAll(bytes.NewReader([]byte("Hello World")))


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 89 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信