gpt4 book ai didi

logging - 如何向 io.MultiWriter 添加/删除按需编写器?

转载 作者:IT王子 更新时间:2023-10-29 02:23:03 26 4
gpt4 key购买 nike

我正在将日志写入文件和程序的标准输入,使用如下内容:

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

但是如果命令退出、被终止或者我只想添加另一个 Writer , 我怎么能把它附加到现有的 logger

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

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

但想知道是否有更好的方法来做到这一点,如果通过创建一个新的 log.New,我应该关闭以前的那些,还是他们只是共享 Writers< 的引用 我传递给 multi var?

最佳答案

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

package main

import (
"io"
"os"
)

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) {
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.writers = append(t.writers, writers...)
}

type multiWriter struct {
writers []io.Writer
}

func (t *multiWriter) Write(p []byte) (n int, err error) {
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) {
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{w}
}

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

并发安全:

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

关于logging - 如何向 io.MultiWriter 添加/删除按需编写器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38420618/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com