我试图将日志消息存储在缓冲区中,以便仅在出现错误时访问它们。有点像智能日志处理中的机会日志记录。在这个例子中,我每 5 秒从缓冲区中获取日志,但是当我使用go run -race code.go.我正在使用渠道进行交流,但显然我做错了。package mainimport ( "bytes" "fmt" "io/ioutil" "log" "time")type LogRequest struct { Buffer chan []byte}type LogBuffer struct { LogInputChan chan []byte LogRequests chan LogRequest}func (f LogBuffer) Write(b []byte) (n int, err error) { f.LogInputChan <- b return len(b), nil}func main() { var logBuffer LogBuffer logBuffer.LogInputChan = make(chan []byte, 100) logBuffer.LogRequests = make(chan LogRequest, 100) log.SetOutput(logBuffer) // store the log messages in a buffer until we ask for it go func() { buf := new(bytes.Buffer) for { select { // receive log messages case logMessage := <-logBuffer.LogInputChan: buf.Write(logMessage) // <- data race case logRequest := <-logBuffer.LogRequests: c, errReadAll := ioutil.ReadAll(buf) if errReadAll != nil { panic(errReadAll) } logRequest.Buffer <- c } } }() // log a test message every 1 second go func() { for i := 0; i < 30; i++ { log.Printf("test: %d", i) // <- data race time.Sleep(1 * time.Second) } }() // print the log every 5 seconds go func() { for { time.Sleep(5 * time.Second) var logRequest LogRequest logRequest.Buffer = make(chan []byte, 1) logBuffer.LogRequests <- logRequest buffer := <-logRequest.Buffer fmt.Printf("**** LOG *****\n%s**** END *****\n\n", buffer) } }() time.Sleep(45 * time.Second)}
1 回答
翻阅古今
TA贡献1780条经验 获得超5个赞
该log包使用内部缓冲区来构建用于输出的日志消息(log/Logger 中的buf字段)。它组成标题,附加调用者提供的数据,然后将此缓冲区传递给您的 方法以进行输出。Write
为了减少分配,log包为每个日志消息回收这个缓冲区。文档中没有说明,但隐含的假设是您的Write方法仅[]byte在Write调用期间使用提供的数据。这个假设适用于大多数输出,例如文件或 STDOUT。
为避免数据竞争,您需要在从Write函数返回之前对传入数据进行显式复制:
func (f LogBuffer) Write(b []byte) (n int, err error) {
z := make([]byte, len(b))
copy(z, b)
f.LogInputChan <- z
return len(b), nil
}
- 1 回答
- 0 关注
- 201 浏览
添加回答
举报
0/150
提交
取消