[英]GoLang chaining io.Reader
我正在嘗試實現一個代理模式來鏈接 io.Reader 上的轉換,以便有效地處理字節塊。
我們不能在接收器上使用指針,所以我的解決方案似乎不是很有效
下面的代碼說“過程花費太長時間”
完整示例位於: 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
}
下面的代碼說“過程花費太長時間”
為什么這段代碼不起作用?
在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.