在 Go 的實(shí)現(xiàn)中(l *Logger) Output,為什么要先獲取互斥鎖 if l.flag&(Lshortfile|Llongfile) != 0 {?func (l *Logger) Output(calldepth int, s string) error { now := time.Now() // get this early. var file string var line int l.mu.Lock() defer l.mu.Unlock() if l.flag&(Lshortfile|Llongfile) != 0 { // Release lock while getting caller info - it's expensive. l.mu.Unlock() var ok bool _, file, line, ok = runtime.Caller(calldepth) if !ok { file = "???" line = 0 } l.mu.Lock() } l.buf = l.buf[:0] l.formatHeader(&l.buf, now, file, line) l.buf = append(l.buf, s...) if len(s) == 0 || s[len(s)-1] != '\n' { l.buf = append(l.buf, '\n') } _, err := l.out.Write(l.buf) return err}那這個(gè)呢?func (l *Logger) Output(calldepth int, s string) error { now := time.Now() // get this early. var file string var line int if l.flag&(Lshortfile|Llongfile) != 0 { var ok bool _, file, line, ok = runtime.Caller(calldepth) if !ok { file = "???" line = 0 } } // acquire mutex here, avoid aquire mutex twice. l.mu.Lock() defer l.mu.Unlock() l.buf = l.buf[:0] l.formatHeader(&l.buf, now, file, line) l.buf = append(l.buf, s...) if len(s) == 0 || s[len(s)-1] != '\n' { l.buf = append(l.buf, '\n') } _, err := l.out.Write(l.buf) return err}
1 回答

飲歌長(zhǎng)嘯
TA貢獻(xiàn)1951條經(jīng)驗(yàn) 獲得超3個(gè)贊
Logger.flag是受互斥體保護(hù)的字段,而不是常量。
log.Logger有一個(gè)SetFlags方法,可以隨時(shí)從任何 goroutine 調(diào)用。該方法實(shí)現(xiàn)為:
// SetFlags sets the output flags for the logger.
// The flag bits are Ldate, Ltime, and so on.
func (l *Logger) SetFlags(flag int) {
l.mu.Lock()
defer l.mu.Unlock()
l.flag = flag
}
文檔本身清楚地表明記錄器可以安全地并發(fā)使用:
一個(gè) Logger 可以同時(shí)從多個(gè) goroutine 中使用;...
為確保這一保證,任何Logger可以修改的字段都必須同步。如果您在l.flag沒(méi)有正確同步的情況下訪問(wèn),您將引入競(jìng)爭(zhēng)條件。
- 1 回答
- 0 關(guān)注
- 128 瀏覽
添加回答
舉報(bào)
0/150
提交
取消