btcd-go 中l(wèi)og部分代碼
整體設(shè)計(jì)
interface : Logger
struct: slog
struct: Backend
Backend
type Backend struct {
w io.Writer
mu sync.Mutex // ensures atomic writes
flag uint32
}
主要實(shí)現(xiàn)了線程安全的print, printf功能何吝,即格式化要打印日志灼擂。 w 這個(gè)writer做為初始參數(shù)走贪,可以從外面?zhèn)鬏斍蚯校鈽?gòu)writer勾徽,方便自己配置writer,比如std.Out/std.Err 等實(shí)現(xiàn)了Writer接口的struct即可谓谦。
Backend還實(shí)現(xiàn)了一個(gè)創(chuàng)建實(shí)例的工廠函數(shù):
func (b* Backend) Logger(subsystemTag string) Logger {
return &slog{LevelInfo, subsystemTag, b}
}
slog
type slog struct {
lvl Level
tag string
b *Backend
}
這個(gè)類實(shí)現(xiàn)了interface: Logger所有接口贫橙。 而內(nèi)部實(shí)現(xiàn)事業(yè) Backend. 通過(guò)Level來(lái)控制日志顯示級(jí)別。 tag來(lái)標(biāo)識(shí)日志來(lái)自某個(gè)子系統(tǒng) subsystem.
以字符形式反粥,按固定長(zhǎng)度輸出數(shù)字卢肃,長(zhǎng)度不夠,前面用0補(bǔ)齊才顿。
但是這個(gè)算法莫湘,只要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 這個(gè)byte slice賦值為0
多go routine下逊脯,使用pool來(lái)
var bufferPool = sync.Pool{
New: func() interface{} {
b := make([]byte, 0, 120)
return &b
},
}
如果有多個(gè)go routine 輸出日志,可使用pool來(lái)避免竣贪,競(jìng)爭(zhēng)同一個(gè)緩存军洼,如使用同一個(gè)緩存巩螃,會(huì)導(dǎo)致其他go routine掛起,而只在writer寫數(shù)據(jù)時(shí)匕争,才使用Mutex來(lái)同步避乏,這樣效率更高,用空間換時(shí)間甘桑。