简体   繁体   English

如何从同一个 io.Reader 读取多次

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

I want to use request.Body(type io.ReadCloser) which is containing a image.我想使用包含图像的request.Body(type io.ReadCloser)

I dont want to use ioutil.ReadAll() as i want to write this body directly to the file as well as want to decode it, so i only want to use the reference to the content to pass to further function calls,我不想使用ioutil.ReadAll()因为我想将此正文直接写入文件并对其进行解码,所以我只想使用对内容的引用来传递给进一步的 function 调用,

I tried creating multiple instances of reader for example shown below我尝试创建多个阅读器实例,例如如下所示

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

}

but in second call it always results into nil .但在第二次调用中,它总是导致nil

Please help me how can i pass multiple separate reference for the same reader?请帮助我如何为同一读者传递多个单独的参考?

io.Reader is treated like a stream. io.Reader被视为流。 Because of this you cannot read it twice.正因为如此,你不能读两遍。 Imagine the an incoming TCP connection.想象一下传入的 TCP 连接。 You cannot rewind the whats coming in.你不能倒带进来的东西。

But you can use the io.TeeReader to duplicate the stream:但是您可以使用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)) 
}

Example on Go Playground Go Playground示例

Edit: As @mrclx pointed out: You need to read from the TeeReader first, otherwise the buffer will be empty.编辑:正如@mrclx 指出的:您需要TeeReader读取,否则缓冲区将为空。

When you call ReadAll it's going to empty the buffer, so the second call will always return nothing.当您调用ReadAll它将清空缓冲区,因此第二次调用将始终不返回任何内容。 What you could do is save the result of ReadAll and reuse that in your functions.您可以做的是保存ReadAll的结果并在您的函数中重用它。 For example:例如:

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

When you read from ioutil.ReadAll(r) then, the content is gone.当您从 ioutil.ReadAll(r) 读取时,内容消失了。 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))

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

@TheHippo答案是正确的我只是想添加它(但无法添加它,因为我只有49个声誉:():首先使用TeeReader并在使用缓冲区之后重要信息,否则第二个缓冲区将为空。

Clone the Reader struct.克隆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.

相关问题 base64 编码 io.Reader - base64 encode io.Reader 如何让Lambda不触发多次? - How to keep Lambda from triggering multiple times? golang reader.Read()可以到达EOF,但是reader.ReadAt()以死循环方式读取相同的数据,没有到达EOF? - golang reader.Read() can arrived EOF, but reader.ReadAt() read same data in dead loop way, not arrived EOF? Azure 管道多次检查相同的回购协议 - Azure Pipeline checkout same repo multiple times 类型 io.invertase.firebase.BuildConfig 被定义多次 - Type io.invertase.firebase.BuildConfig is defined multiple times 在 Firebase 模拟器中一次更新后多次读取 Firestore 文档 - Firestore document is read multiple times after a single update in Firebase emulator Python BigQuery 客户端多次执行相同的查询 - Python BigQuery client executing same query multiple times Spring 批量读取器更改为从 GCP 云存储桶读取文件内容 - Spring batch reader changes to read file content from GCP cloud storage bucket AWS Amplify Authentication 使用相同的 email 多次登录 - AWS Amplify Authentication sign in multiple times with same email Azure 事件触发器多次触发同一个文件 - Azure Event Trigger fires multiple times same file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM