英文:
Synchronising writes to io.MultiWriter in golang
问题
我正在开发一个应用程序,它应该能够同时写入bytes.Buffer
和os.Stdout
/os.Stderr
。
因此,我创建了一个:
w := io.MultiWriter(myBuf, os.Stdout)
这些写操作将来自多个goroutine
。
为了使我的bytes.Buffer
至少是线程安全的,我进行了封装:
type Buffer struct {
buffer bytes.Buffer
mutex sync.Mutex
}
func (s *Buffer) Write(p []byte) (n int, err error) {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.buffer.Write(p)
}
func (s *Buffer) String() string {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.buffer.String()
}
如何使用标准错误/输出写入实现相同的结果?
我考虑使用log
,但它没有实现io.Writer
接口。
英文:
I am working on an app that should be able to write to both a bytes.Buffer
as well to os.Stdout
/ os.Stderr
.
Therefore I am creating an
w := io.MultiWriter(myBuf, os.Stdout)
The writes will be from multiple goroutines
.
To make at least my bytes.Buffer
thread safe, I am wrapping it
type Buffer struct {
buffer bytes.Buffer
mutex sync.Mutex
}
func (s *Buffer) Write(p []byte) (n int, err error) {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.buffer.Write(p)
}
func (s *Buffer) String() string {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.buffer.String()
}
How can I achieve the same result with the standard error / output writes?
I thought about using log
but it does not implement the io.Writer
interface.
答案1
得分: 1
如何使用标准错误/输出写入来实现相同的结果?
使用互斥锁(mutex),就像你说的那样。
我考虑过使用日志(log),但它没有实现io.Writer接口。
有趣的想法,因为它会自动锁定自身,但你可以使用普通的os.Stdout
和os.Stderr
来实现,它们都实现了io.Writer
接口:
package main
import (
"fmt"
"io"
"os"
"sync"
)
type LockedWriter struct {
w io.Writer
l sync.Mutex
}
func (lw *LockedWriter) Write(p []byte) (n int, err error) {
lw.l.Lock()
defer lw.l.Unlock()
return lw.w.Write(p)
}
func main() {
var wg sync.WaitGroup
var w = &LockedWriter{
w: io.MultiWriter(os.Stdout, os.Stderr),
}
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
for j := 0; j < i; j++ {
fmt.Fprintf(w, "I am goroutine %d (%d/%d)\n", i, j, i)
}
wg.Done()
}(i)
}
wg.Wait()
}
在这种特定情况下,我无法复现任何插入写入,但我认为如果消息足够长或goroutine执行更多操作,就会出现插入写入。
英文:
> How can I achieve the same result with the standard error / output writes?
With a mutex, like you said.
> I thought about using log but it does not implement the io.Writer interface.
Interesting idea, since it locks itself, but you can do this with plain old os.Stdout
and os.Stderr
, both of which implement io.Writer
:
package main
import (
"fmt"
"io"
"os"
"sync"
)
type LockedWriter struct {
w io.Writer
l sync.Mutex
}
func (lw *LockedWriter) Write(p []byte) (n int, err error) {
lw.l.Lock()
defer lw.l.Unlock()
return lw.w.Write(p)
}
func main() {
var wg sync.WaitGroup
var w = &LockedWriter{
w: io.MultiWriter(os.Stdout, os.Stderr),
}
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
for j := 0; j < i; j++ {
fmt.Fprintf(w, "I am goroutine %d (%d/%d)\n", i, j, i)
}
wg.Done()
}(i)
}
wg.Wait()
}
In this particular case, I couldn't reproduce any interpolated writes, but I think if the messages were long enough or the goroutines were doing more operations, I would.
答案2
得分: 0
这将有所帮助:
type StdoutType {
stdout *File
mutex sync.Mutex
}
func NewStdoutType() *StdoutType {
return &StdoutType{
stdout: os.Stdout,
}
}
func (s *StdoutType) Write(p []byte) (n int, err error) {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.stdout.Write(p)
}
StdoutType
现在与 io.Writer
兼容。
英文:
Will this help:
type StdoutType {
stdout *File
mutex sync.Mutex
}
func NewStdoutType() *StdoutType {
return &StdoutType{
stdout: os.Stdout,
}
}
func (s *StdoutType) Write(p []byte) (n int, err error) {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.stdout.Write(p)
}
StdoutType
is now io.Writer
compatible
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论