繁体   English   中英

GoLang 链接 io.Reader

[英]GoLang chaining io.Reader

我正在尝试实现一个代理模式来链接 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]))
    }
}

每次在transformReaderHandler上调用Read您都在复制bytes.Buffer值,因此您永远无法通过缓冲区。 您必须使用*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

下面的代码说“过程花费太长时间”

为什么这段代码不起作用?

transformReaderHandler.Read()方法中,您有一个值接收器。 这意味着每次调用Read() ,它都会获取调用它的实例的副本 然后,当您调用(*bytes.Buffer)(&t).Read(p) ,它会修改该实例的内部状态,以便下次读取时,它会从之前读取的点之后读取。

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

为了快速检查这确实是由于值接收器,您可以使用指针接收器定义transformReaderHandler.Read()并将t存储为t = (*transformReaderHandler)(b) 我会让你检查它的作用。 (编辑:涉及嵌入的正确解决方案在评论中)

你有更高效(内存高效、计算高效)的解决方案吗?

如果您只是在寻找缓冲 IO 以提高读取效率,请查看bufio.NewReader() 如果这还不够,您可以从中io.Reader灵感并环绕一个io.Reader接口,而不是环绕一个bytes.Buffer实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM