Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Logging 如何向io.MultiWriter添加/删除按需写入程序?_Logging_Go - Fatal编程技术网

Logging 如何向io.MultiWriter添加/删除按需写入程序?

Logging 如何向io.MultiWriter添加/删除按需写入程序?,logging,go,Logging,Go,我正在将日志写入一个文件和一个程序的标准输入,例如: type myLogger { log *log.Logger } cmd := exec.Command("logger", "-t", "test") w, _ = cmd.StdinPipe() multi := io.MultiWriter(file, w) myLog := myLogger{log.New(multi, "", log.Ldate|log.Ltime)} 但是,如果命令退出、被终止,或者如果我只想

我正在将日志写入一个文件和一个程序的标准输入,例如:

type myLogger {
    log  *log.Logger
}

cmd := exec.Command("logger", "-t", "test")
w, _ = cmd.StdinPipe()

multi := io.MultiWriter(file, w)

myLog := myLogger{log.New(multi, "", log.Ldate|log.Ltime)}
但是,如果命令退出、被终止,或者如果我只想添加另一个命令,我如何将其附加到现有命令

目前,对于每一个更改,我都会创建一个新的
multi
,并覆盖现有的记录器:

multi := io.MultiWriter(file, w)
myLog.log = log.New(multi, "", log.Ldate|log.Ltime)

但是想知道是否有更好的方法,是否通过创建一个新的
log.new
,我应该关闭前面的那些,还是他们只是共享我传递给
multi
var的
编写者的引用?

您可以编写自己的包,并添加这两个
Remove
Append
方法,就像这个工作测试示例代码(不是并发的):

并发安全:

package main

import (
    "io"
    "os"
    "sync"
)

func main() {
    w1, e := os.Create("file1.txt")
    if e != nil {
        panic(e)
    }
    w2, e := os.Create("file2.txt")
    if e != nil {
        panic(e)
    }
    mw := MultiWriter(w1, w2)
    data := []byte("Hello ")
    _, e = mw.Write(data)
    if e != nil {
        panic(e)
    }

    var m *multiWriter = mw.(*multiWriter)
    m.Remove(w2)
    w2.Close()
    w3, e := os.Create("file3.txt")
    if e != nil {
        panic(e)
    }
    m.Append(w3)
    data = []byte("World ")
    _, e = mw.Write(data)
    if e != nil {
        panic(e)
    }
    w3.Close()
    w1.Close()
}
func (t *multiWriter) Remove(writers ...io.Writer) {
    t.mu.Lock()
    defer t.mu.Unlock()
    for i := len(t.writers) - 1; i > 0; i-- {
        for _, v := range writers {
            if t.writers[i] == v {
                t.writers = append(t.writers[:i], t.writers[i+1:]...)
                break
            }
        }
    }
}
func (t *multiWriter) Append(writers ...io.Writer) {
    t.mu.Lock()
    defer t.mu.Unlock()
    t.writers = append(t.writers, writers...)
}

type multiWriter struct {
    writers []io.Writer
    mu      sync.Mutex
}

func (t *multiWriter) Write(p []byte) (n int, err error) {
    t.mu.Lock()
    defer t.mu.Unlock()
    for _, w := range t.writers {
        n, err = w.Write(p)
        if err != nil {
            return
        }
        if n != len(p) {
            err = io.ErrShortWrite
            return
        }
    }
    return len(p), nil
}

var _ stringWriter = (*multiWriter)(nil)

func (t *multiWriter) WriteString(s string) (n int, err error) {
    t.mu.Lock()
    defer t.mu.Unlock()
    var p []byte // lazily initialized if/when needed
    for _, w := range t.writers {
        if sw, ok := w.(stringWriter); ok {
            n, err = sw.WriteString(s)
        } else {
            if p == nil {
                p = []byte(s)
            }
            n, err = w.Write(p)
        }
        if err != nil {
            return
        }
        if n != len(s) {
            err = io.ErrShortWrite
            return
        }
    }
    return len(s), nil
}

// MultiWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command.
func MultiWriter(writers ...io.Writer) io.Writer {
    w := make([]io.Writer, len(writers))
    copy(w, writers)
    return &multiWriter{writers: w}
}

// stringWriter is the interface that wraps the WriteString method.
type stringWriter interface {
    WriteString(s string) (n int, err error)
}

您可以编写自己的包并添加这两个
Remove
Append
方法,就像这个工作测试示例代码一样(不是并发的):

并发安全:

package main

import (
    "io"
    "os"
    "sync"
)

func main() {
    w1, e := os.Create("file1.txt")
    if e != nil {
        panic(e)
    }
    w2, e := os.Create("file2.txt")
    if e != nil {
        panic(e)
    }
    mw := MultiWriter(w1, w2)
    data := []byte("Hello ")
    _, e = mw.Write(data)
    if e != nil {
        panic(e)
    }

    var m *multiWriter = mw.(*multiWriter)
    m.Remove(w2)
    w2.Close()
    w3, e := os.Create("file3.txt")
    if e != nil {
        panic(e)
    }
    m.Append(w3)
    data = []byte("World ")
    _, e = mw.Write(data)
    if e != nil {
        panic(e)
    }
    w3.Close()
    w1.Close()
}
func (t *multiWriter) Remove(writers ...io.Writer) {
    t.mu.Lock()
    defer t.mu.Unlock()
    for i := len(t.writers) - 1; i > 0; i-- {
        for _, v := range writers {
            if t.writers[i] == v {
                t.writers = append(t.writers[:i], t.writers[i+1:]...)
                break
            }
        }
    }
}
func (t *multiWriter) Append(writers ...io.Writer) {
    t.mu.Lock()
    defer t.mu.Unlock()
    t.writers = append(t.writers, writers...)
}

type multiWriter struct {
    writers []io.Writer
    mu      sync.Mutex
}

func (t *multiWriter) Write(p []byte) (n int, err error) {
    t.mu.Lock()
    defer t.mu.Unlock()
    for _, w := range t.writers {
        n, err = w.Write(p)
        if err != nil {
            return
        }
        if n != len(p) {
            err = io.ErrShortWrite
            return
        }
    }
    return len(p), nil
}

var _ stringWriter = (*multiWriter)(nil)

func (t *multiWriter) WriteString(s string) (n int, err error) {
    t.mu.Lock()
    defer t.mu.Unlock()
    var p []byte // lazily initialized if/when needed
    for _, w := range t.writers {
        if sw, ok := w.(stringWriter); ok {
            n, err = sw.WriteString(s)
        } else {
            if p == nil {
                p = []byte(s)
            }
            n, err = w.Write(p)
        }
        if err != nil {
            return
        }
        if n != len(s) {
            err = io.ErrShortWrite
            return
        }
    }
    return len(s), nil
}

// MultiWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command.
func MultiWriter(writers ...io.Writer) io.Writer {
    w := make([]io.Writer, len(writers))
    copy(w, writers)
    return &multiWriter{writers: w}
}

// stringWriter is the interface that wraps the WriteString method.
type stringWriter interface {
    WriteString(s string) (n int, err error)
}

如果要在log.Logger中使用此项,则应确保并发访问的安全性,因为Logger本身可以并发使用。@JimB如果我是对的,请解释/共享一个链接,以更好地理解/了解如何确保安全。这意味着要在log.Logger中使用
sync.mutex
?如果要在log.Logger中使用此项,同时访问应该是安全的,因为记录器本身可以同时使用。@JimB如果我是对的,请您解释/共享一个链接,以便更好地理解/了解如何确保安全。这意味着使用了
sync.mutex