簡體   English   中英

如何從同一個 io.Reader 讀取多次

[英]How to read multiple times from same io.Reader

我想使用包含圖像的request.Body(type io.ReadCloser)

我不想使用ioutil.ReadAll()因為我想將此正文直接寫入文件並對其進行解碼,所以我只想使用對內容的引用來傳遞給進一步的 function 調用,

我嘗試創建多個閱讀器實例,例如如下所示

package main

import (
    "io/ioutil"
    "log"
    "strings"
)


func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")
    a := &r
    b := &r
    log.Println(ioutil.ReadAll(*a))
    log.Println(ioutil.ReadAll(*b))

}

但在第二次調用中,它總是導致nil

請幫助我如何為同一讀者傳遞多個單獨的參考?

io.Reader被視為流。 正因為如此,你不能讀兩遍。 想象一下傳入的 TCP 連接。 你不能倒帶進來的東西。

但是您可以使用io.TeeReader來復制流:

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

Go Playground示例

編輯:正如@mrclx 指出的:您需要TeeReader讀取,否則緩沖區將為空。

當您調用ReadAll它將清空緩沖區,因此第二次調用將始終不返回任何內容。 您可以做的是保存ReadAll的結果並在您的函數中重用它。 例如:

bytes, _ := ioutil.ReadAll(r);
log.Println(string(bytes))

當您從 ioutil.ReadAll(r) 讀取時,內容消失了。 你不能讀第二遍。 例如:

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))

從技術上講,在一個閱讀器上,您不能多次閱讀。

  • 即使你創建了不同的引用但是
  • 當您閱讀一次時,它將是所有引用所引用的同一對象。
  • 所以你可以做的是讀取內容並將其存儲在一個變量中。
  • 然后根據需要多次使用該變量。

這將打印兩次。

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

@TheHippo答案是正確的我只是想添加它(但無法添加它,因為我只有49個聲譽:():首先使用TeeReader並在使用緩沖區之后重要信息,否則第二個緩沖區將為空。

克隆Reader結構。

package main

import (
    "io/ioutil"
    "log"
    "strings"
)

func main() {
    r := strings.NewReader("some io.Reader stream to be read\n")
    v := new(strings.Reader)
    *v = *r
    log.Println(ioutil.ReadAll(r))
    log.Println(ioutil.ReadAll(v))

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM