2016-07-28 29 views
1

我想創建一個設置爲特定log.Logger的所有內容都附加到特定變量的字符串數組的情況。io.MultiWriter與golang的pass-by-value

變量的類型實現了io.Writer接口,所以它應該很容易通過io.MultiWriter添加到log.New(),但我似乎遇到了棘手的問題:io.Writer接口是固定的並且根據給定golang的傳值,變量不可能引用它自己。

也許會更有意義有一個例子:

package main 

import "fmt" 
import "io" 
import "log" 
import "os" 
import "strings" 

var Log *log.Logger 

type Job_Result struct { 
    Job_ID int64 
    // other stuff 
    Log_Lines []string 
} 

// satisfies io.Writer interface 
func (jr Job_Result) Write (p []byte) (n int, err error) { 
    s := strings.TrimRight(string(p),"\n ") 
    jr.Log_Lines= append(jr.Log_Lines,s) 
    return len(s), nil 
} 

func (jr Job_Result) Dump() { 
    fmt.Println("\nHere is a dump of the job result log lines:") 
    for n, s := range jr.Log_Lines{ 
     fmt.Printf("\tline %d: %s\n",n,s) 
    } 
} 

func main() { 

    // make a Job_Result 

    var jr Job_Result 
    jr.Job_ID = 123 
    jr.Log_Lines = make([]string,0) 

    // create an io.MultiWriter that points to both stdout 
    // and that Job_Result var 

    var writers io.Writer 
    writers = io.MultiWriter(os.Stdout,jr) 

    Log = log.New(writers, 
     "", 
     log.Ldate|log.Ltime|log.Lshortfile) 

    // send some stuff to the log 

    Log.Println("program starting") 
    Log.Println("something happened") 
    Log.Printf("last thing that happened, should be %drd line\n",3) 

    jr.Dump() 

} 

這是輸出,這並不奇怪:

2016/07/28 07:20:07 testjob.go:43: program starting 
2016/07/28 07:20:07 testjob.go:44: something happened 
2016/07/28 07:20:07 testjob.go:45: last thing that happened, should be 3rd line 

Here is a dump of the job result log lines: 

我理解這個問題 - 寫()是得到一個副本的Job_Result變量,所以它忠實地追加,然後副本消失,因爲它是本地的。我應該傳遞一個指向Job_Result的指針......但我不是那個叫Write()的人,它是由Logger完成的,我不能改變它。我認爲這是一個簡單的解決方案來捕獲日誌輸出到數組中(還有其他訂閱/取消訂閱的東西,我沒有顯示),但這一切都歸結爲這個問題的io.Write()接口。

飛行員誤差?糟糕的設計?我不是在追求什麼?感謝您的任何建議。

回答

2

重新定義寫入功能(現在指針接收器)

// satisfies io.Writer interface 
func (jr *Job_Result) Write (p []byte) (n int, err error) { 
    s := strings.TrimRight(string(p),"\n ") 
    jr.Log_Lines= append(jr.Log_Lines,s) 
    return len(s), nil 
} 

初始化

jr := new(Job_Result) // makes a pointer. 

其餘部分保持原樣。這樣,*Job_Result仍然實現io.Writer,但不失去狀態。

go教程已經說過,當一個方法修改接收器時,您應該使用指針接收器,否則更改可能會丟失。使用指針而不是實際對象沒有什麼不利之處,當你想確定時,只有一個對象。 (是的,它在技術上不是一個對象)。

+0

簡單而優雅。我過分關注確保Write()簽名匹配,我忘記了其餘部分。非常感謝! – raindog308