在golang中同步写入io.MultiWriter

huangapple go评论75阅读模式
英文:

Synchronising writes to io.MultiWriter in golang

问题

我正在开发一个应用程序,它应该能够同时写入bytes.Bufferos.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.Stdoutos.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 (
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;os&quot;
	&quot;sync&quot;
)

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 = &amp;LockedWriter{
		w: io.MultiWriter(os.Stdout, os.Stderr),
	}
	for i := 0; i &lt; 10; i++ {
		wg.Add(1)
		go func(i int) {
			for j := 0; j &lt; i; j++ {
				fmt.Fprintf(w, &quot;I am goroutine %d (%d/%d)\n&quot;, 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 &amp;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

huangapple
  • 本文由 发表于 2021年10月6日 20:33:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/69465797.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定