我試圖將日志消息存儲在緩沖區中,以便僅在出現錯誤時訪問它們。有點像智能日志處理中的機會日志記錄。在這個例子中,我每 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 關注
- 228 瀏覽
添加回答
舉報
0/150
提交
取消