io.MultiWriter与golang的pass-by-value相比

时间:2016-07-28 14:30:44

标签: go

我想创建一种情况,其中设置为特定log.Logger的所有内容也会附加到特定变量的字符串数组中。

变量的类型实现了io.Writer接口,所以应该很容易通过io.MultiWriter将它添加到log.New(),但我似乎遇到了一个棘手的问题:io.Writer界面是固定的,并且由于golang的传值,变量无法引用它。

通过一个例子可能会更有意义:

OtherVendorClass<T>

这是输出,这并不奇怪:

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()   

}

我理解这个问题 - Write()正在获取Job_Result变量的副本,因此它会尽职尽责地附加,然后副本会因为它本地而消失。我应该向它传递一个指向Job_Result的指针...但我不是那个调用Write()的人,它是由Logger完成的,我无法改变它。

我认为这是将日志输出捕获到数组中的简单解决方案(还有其他我没有展示的订阅/取消订阅内容),但这一切都归结为这个有问题的io.Write()接口。

试点错误?糟糕的设计?我不喜欢什么?谢谢你的任何建议。

1 个答案:

答案 0 :(得分: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教程已经说过,当一个方法修改接收器时,你应该使用指针接收器,否则更改可能会丢失。使用指针而不是实际对象有一点缺点,当你想确定时,只有一个对象。 (是的,它在技术上不是一个对象)。