How to read multiple times from same io.Reader

后端 未结 4 1820
一整个雨季
一整个雨季 2020-12-14 14:33

I want to use request.Body(type io.ReadCloser) which is containing a image.

I dont want to use ioutil.ReadAll() as i want to write this bod

相关标签:
4条回答
  • 2020-12-14 14:56

    When you read from ioutil.ReadAll(r) then, the content is gone. You can’t read from it a second time. For an example:

    var response *http.Response
    
    //Read the content
    rawBody, err := ioutil.ReadAll(response.Body)
        if err != nil {
            t.Error(err)
        }
    
    // Restore the io.ReadCloser to it's original state
    response.Body = ioutil.NopCloser(bytes.NewBuffer(rawBody))
    
    0 讨论(0)
  • 2020-12-14 14:57

    Technically, on one reader, you cannot read multiple times.

    • Even if you create different references but
    • when you read once it will be same object referred by all references.
    • so what you can do is read the content and store it in one variable.
    • Then use that variable as many times as you want.

    This will print twice.

    package main
    
    import (
        "io/ioutil"
        "log"
        "strings"
    )
    
    func main() {
        r := strings.NewReader("some io.Reader stream to be read\n")
        stringData, _ := ioutil.ReadAll(r)
        log.Println(stringData)
        log.Println(stringData)
    }
    
    0 讨论(0)
  • 2020-12-14 14:58

    io.Reader is treated like a stream. Because of this you cannot read it twice. Imagine the an incoming TCP connection. You cannot rewind the whats coming in.

    But you can use the io.TeeReader to duplicate the stream:

    package main
    
    import (
        "bytes"
        "io"
        "io/ioutil"
        "log"
        "strings"
    )
    
    func main() {
        r := strings.NewReader("some io.Reader stream to be read\n")
        var buf bytes.Buffer
        tee := io.TeeReader(r, &buf)
    
        log.Println(ioutil.ReadAll(tee))
        log.Println(ioutil.ReadAll(&buf)) 
    }
    

    Example on Go Playground

    Edit: As @mrclx pointed out: You need to read from the TeeReader first, otherwise the buffer will be empty.

    0 讨论(0)
  • 2020-12-14 15:04

    When you call ReadAll it's going to empty the buffer, so the second call will always return nothing. What you could do is save the result of ReadAll and reuse that in your functions. For example:

    bytes, _ := ioutil.ReadAll(r);
    log.Println(string(bytes))
    
    0 讨论(0)
提交回复
热议问题