登录
首页 >  Golang >  Go问答

GoLang 链接 io.Reader

来源:stackoverflow

时间:2024-04-18 15:27:33 328浏览 收藏

本篇文章给大家分享《GoLang 链接 io.Reader》,覆盖了Golang的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。

问题内容

我正在尝试实现代理模式来链接 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() 方法中,您有一个值接收器。这意味着每次调用 read() 时,它都会获得调用它的实例的副本。然后,当您调用 (*bytes.buffer)(&t).read(p) 时,它会修改该实例的内部状态,以便下次读取时,它从之前读取的点之后读取。 p>

现在因为实例是副本,所以方法退出后就被丢弃,原来的实例保持不变。因此,每次调用 read() 时,bytes.buffer.read() 仅读取前几个字节。为了证明这一点,请在调用 read() 后在 readbychunk() 内添加一条语句 fmt.println("n=", n, "err=", err)

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

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

如果您只是在寻找缓冲 io 以实现更高效的读取,请查看 bufio.NewReader()。如果这还不够,您可以从中获取灵感并包装 io.reader 接口,而不是包装 bytes.buffer 实例.

每次在 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

理论要掌握,实操不能落!以上关于《GoLang 链接 io.Reader》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>