btcd-go 中log部分代碼
整體設計
interface : Logger struct: slog struct: Backend
Backend
type Backend struct { w io.Writer mu sync.Mutex // ensures atomic writes flag uint32}
主要實現了安全執行緒的print, printf功能,即格式化要列印日誌。 w 這個writer做為初始參數,可以從外面傳輸,解構writer,方便自己配置writer,比如std.Out/std.Err 等實現了Writer介面的struct即可。
Backend還實現了一個建立執行個體的工廠函數:
func (b* Backend) Logger(subsystemTag string) Logger { return &slog{LevelInfo, subsystemTag, b}}
slog
type slog struct { lvl Level tag string b *Backend}
這個類實現了interface: Logger所有介面。 而內部實現事業 Backend. 通過Level來控制日誌顯示層級。 tag來標識日誌來自某個子系統 subsystem.
以字元形式,按固定長度輸出數字,長度不夠,前面用0補齊。
但是這個演算法,只要i大於0才能正常工作,所以,把i類型改成uint更合適
// From stdlib log package.// Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid// zero-padding.func itoa(buf *[]byte, i int, wid int) { // Assemble decimal in reverse order. var b [20]byte bp := len(b) - 1 for i >= 10 || wid > 1 { wid-- q := i / 10 b[bp] = byte('0' + i - q*10) bp-- i = q } // i < 10 b[bp] = byte('0' + i) *buf = append(*buf, b[bp:]...)}
給slice賦值為0的用法
// recycleBuffer puts the provided byte slice, which should have been obtain via// the buffer function, back on the free list.func recycleBuffer(b *[]byte) { *b = (*b)[:0] bufferPool.Put(b)}
其中的 *b = (*b)[:0] 就是把b 這個byte slice賦值為0
多go routine下,使用pool來
var bufferPool = sync.Pool{ New: func() interface{} { b := make([]byte, 0, 120) return &b },}
如果有多個go routine 輸出日誌,可使用pool來避免,競爭同一個緩衝,如使用同一個緩衝,會導致其他go routine掛起,而只在writer寫資料時,才使用Mutex來同步,這樣效率更高,用空間換時間。
參考