GoLang链接io.Reader

时间:2018-09-06 13:45:44

标签: go

我正在尝试实现代理模式以在io.Reader上进行链式转换,以便有效地处理字节块。

  1. 我们不能在接收器上使用指针,所以我的解决方案似乎效率不高

  2. 下面的代码说“处理时间太长”

完整示例,位于:https://play.golang.org/p/KhM0VXLq4CO

b := bytes.NewBufferString(text)
t := transformReaderHandler(*b)
readByChunk(t)

type transformReaderHandler bytes.Buffer

func (t transformReaderHandler) Read(p []byte) (n int, err error) {
    n, err = (*bytes.Buffer)(&t).Read(p)
    //if n > 0 {
    //  Do Something on the chunk
    //}
    return
}

您是否有任何更有效的(内存效率高,计算效率高的)解决方案?

为什么此代码不起作用?

编辑: @svsd解决方案的实现:https://play.golang.org/p/VUpJcyKLB6D

package main

import (
    "io"
    "fmt"
    "bytes"
)

const text = "Reaaaaally long and complex text to read in chunk"

func main() {
    b := bytes.NewBufferString(text)

    t := (*transformReaderHandler)(b)

    readByChunk(t)
}

type transformReaderHandler bytes.Buffer

func (t *transformReaderHandler) Read(p []byte) (n int, err error) {
    n, err = (*bytes.Buffer)(t).Read(p)
    if n > 0 {
        p[0] = 'X'
    }
    return
}

func readByChunk(r io.Reader) {
    var p = make([]byte, 4)

    for {
        n, err := r.Read(p)
        if err == io.EOF {
            break
        }
        fmt.Println(string(p[:n]))
    }
}

2 个答案:

答案 0 :(得分:4)

每次在bytes.Buffer上调用Read时,您都将复制transformReaderHandler值,因此您将永远无法通过缓冲区。您必须使用*bytes.Buffer指针来避免复制。

transformReaderHandler中嵌入缓冲区(或将其添加为命名字段),因此您可以根据需要调用委托Read方法。

type transformReaderHandler struct {
    *bytes.Buffer
}

func (t *transformReaderHandler) Read(p []byte) (n int, err error) {
    n, err = t.Buffer.Read(p)
    //if n > 0 {
    //  Do Something
    //}
    return
}

https://play.golang.org/p/npZQ4Tz0hhv

答案 1 :(得分:2)

  

下面的代码说“处理时间太长”

     

为什么此代码不起作用?

transformReaderHandler.Read()方法中,您有一个值接收者。这意味着每次调用Read()时,它都会得到调用它的实例的副本。然后,当您再调用(*bytes.Buffer)(&t).Read(p)时,它将修改该实例的内部状态,以便下次阅读时,它将从先前读取的位置开始读取。

现在,因为该实例是一个副本,所以在方法退出并且原始实例保持不变之后,它将被丢弃。因此,每次调用Read()时,bytes.Buffer.Read()仅读取前几个字节。为了证明这一点,请在调用fmt.Println("n=", n, "err=", err)之后在readByChunk()内添加一个语句Read()

要快速检查这确实是由于值接收器引起的,可以使用指针接收器定义transformReaderHandler.Read()并将t存储为t = (*transformReaderHandler)(b)。我让您检查一下它的作用。 (编辑:注释中包含嵌入的正确解决方案)

  

您是否有任何更有效的(内存效率高,计算效率高的)解决方案?

如果您只想寻找缓冲的IO以获得更有效的读取,请查看bufio.NewReader()。如果这还不够的话,您可以从中获得启发并环绕io.Reader接口,而不是环绕bytes.Buffer实例。

相关问题