2016-09-30 104 views
5

我想使用request.Body(type io.ReadCloser)它包含一个图像。Golang从同一个阅读器多次阅读

我不想使用ioutil.ReadAll(),我想直接写本机构的文件,以及要对其进行解码,所以我只希望使用参考内容传递给进一步函数调用,

我试图创建下面

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

请帮助我如何通过多个单独的参考为同一读者?

+3

撤消你问的方式

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

例。使用'io.TeeReader'来捕获您阅读的内容以供进一步参考,例如在'bytes.Buffer'中。 – Volker

回答

3

当你呼叫ReadAll它将清空缓冲区,所以第二个呼叫将永远不会返回任何内容。你可以做的是保存ReadAll的结果并在你的函数中重用。例如:

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

从技术上讲,在一台阅读器上,不能多次阅读。

  • 即使你创建不同的引用
  • 当你读一次,这将是所有参考提到相同的对象。
  • 所以你可以做的是读取内容并将其存储在一个变量中。
  • 然后根据需要多次使用该变量。

这将打印两次。

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

我想知道为什么不能:-) –

+2

@AbhishekSoni:'io.Reader'是一个流。一旦你完成了流,没有更多。如果你阅读了一部分流,下一次阅读继续你离开的地方。 – JimB

8

io.Reader被视为流。正因为如此,你不能读它两次。想象一下传入的TCP连接。你不能倒带什么在未来

但是你可以使用io.TeeReader复制流:上Go Playground