亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

golang 代理 io.Writer 在 log.Logger 中使用時表現不同

golang 代理 io.Writer 在 log.Logger 中使用時表現不同

Go
瀟湘沐 2023-04-24 15:55:56
我正在嘗試實現一個滿足 io.Writer 要求的代理,因此我可以將其插入記錄器。這個想法是它會像平常一樣打印輸出,但也會保留一份數據副本供以后讀取。以下代碼中的 ProxyIO 結構應該執行此操作,而且只要我直接調用其 Write() 方法,它確實會執行此操作。但是,當我將它插入 log.Logger 實例時,輸出是意外的。(這是精簡代碼,我想使用的原始實現是使用映射和循環指針,而不是[][]byte示例代碼中使用的 buf。我還刪除了所有鎖定。)package mainimport (    "fmt"    "io"    "io/ioutil"    "log")type ProxyIO struct {    out io.Writer // the io we are proxying    buf [][]byte}func newProxyIO(out io.Writer) *ProxyIO {    return &ProxyIO{        out: out,        buf: [][]byte{},    }}func (r *ProxyIO) Write(s []byte) (int, error) {    r.out.Write(s)    r.buf = append(r.buf, s)    return len(s), nil}func main() {    p := newProxyIO(ioutil.Discard)    p.Write([]byte("test1\n"))    p.Write([]byte("test2\n"))    p.Write([]byte("test3\n"))    l := log.New(p, "", 0)    l.Print("test4")    l.Print("test5")    l.Print("test6")    for i, e := range p.buf {        fmt.Printf("%d: %s", i, e)    }}(這里是操場上的代碼https://play.golang.org/p/UoOq4Nd-rmI)我希望這段代碼有以下輸出:0: test11: test22: test33: test44: test55: test6但是,它將始終打?。?: test11: test22: test33: test64: test65: test6我的地圖實現的行為是相同的。我還嘗試使用雙向鏈表作為container/list存儲,它總是一樣的。所以我一定在這里遺漏了一些重要的東西。為什么我在緩沖區中看到了三次最后的日志輸出,而不是最后三行日志輸出?
查看完整描述

1 回答

?
catspeake

TA貢獻1111條經驗 獲得超0個贊

如果您查看源代碼,Logger.Print您會看到它調用logger.Output.?您會注意到它如何將字符串的值設置為l.buf然后調用Write

您會發現即使所有內容都是按值傳遞的

當您將切片傳遞給函數時,將從該標頭制作一個副本,包括指針,該指針將指向相同的后備數組。

所以當你這樣做時:

l.Print("test4")
l.Print("test5")
l.Print("test6")

Logger 有效地重復使用同一個切片,并且您正在append對同一個切片引用 3 次,因此在打印時自然會使用 3 次最新的值集。

[]byte要解決此問題,您可以像這樣在使用之前復制:

func?(r?*ProxyIO)?Write(s?[]byte)?(int,?error)?{
????c?:=?make([]byte,?len(s))
????????copy(c,?s)
????r.out.Write(c)
????r.buf?=?append(r.buf,?c)
????????return?len(c),?nil}
查看完整回答
反對 回復 2023-04-24
  • 1 回答
  • 0 關注
  • 186 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號