Go语言多协程场景下io.MultiWriter写入同步实现方法问询
方案1:实现通用的线程安全Writer封装
你可以参考自定义Buffer的加锁思路,封装一个通用的带互斥锁的io.Writer实现,直接适配标准输出、标准错误流:
import ( "io" "sync" ) type SyncWriter struct { writer io.Writer mu sync.Mutex } func NewSyncWriter(w io.Writer) *SyncWriter { return &SyncWriter{writer: w} } func (sw *SyncWriter) Write(p []byte) (n int, err error) { sw.mu.Lock() defer sw.mu.Unlock() return sw.writer.Write(p) }
使用方式
创建对应标准输出、标准错误的线程安全实例,再传入io.MultiWriter即可:
// 初始化线程安全的标准输出、标准错误 syncStdout := NewSyncWriter(os.Stdout) syncStderr := NewSyncWriter(os.Stderr) // 传入你自己封装的线程安全Buffer,以及同步后的输出流 w := io.MultiWriter(myBuf, syncStdout) // 如果需要同时写stderr也可以加进去:w := io.MultiWriter(myBuf, syncStdout, syncStderr)
补充说明
- 锁的独立性:上述实现中
stdout和stderr的锁是独立的,不会互相阻塞;如果你有强需求要保证两类输出的全局顺序,也可以让二者共用同一个互斥锁。 - 关于log包的误解:你之前认为log包未实现
io.Writer接口其实不准确,log包的打印方法默认自带全局锁保证线程安全,你也可以通过log.SetOutput(targetWriter)的方式绑定输出目标,不过上述自定义SyncWriter的方案更轻量,和你现有代码结构的适配成本更低。 - 原生系统调用的原子性局限:POSIX标准中仅保证小于
PIPE_BUF(多数系统默认4096字节)的单行写入是原子的,如果你要写入的内容长度超过该值、或者是多行内容,即使是系统自带的标准流写入也会出现内容穿插的问题,加锁是必要的。
内容的提问来源于stack exchange,提问作者pkaramol
相关产品推荐
相关产品推荐

