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