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.
CodePudding user response:
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.
CodePudding user response:
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
