golang byte 转writer_聊聊golang的zap的WriteSyncer
序
本文主要研究一下golang的zap的WriteSyncer
WriteSyncer
zap@v1.16.0/zapcore/write_syncer.go
type?WriteSyncer?interface?{????io.Writer????Sync()?error}WriteSyncer內嵌了io.Writer接口,定義了Sync方法
Writer
/usr/local/go/src/io/io.go
type?Writer?interface?{????Write(p?[]byte)?(n?int,?err?error)}Writer接口定義了Write方法
lockedWriteSyncer
zap@v1.16.0/zapcore/write_syncer.go
type?lockedWriteSyncer?struct?{????sync.Mutex????ws?WriteSyncer}func?Lock(ws?WriteSyncer)?WriteSyncer?{????if?_,?ok?:=?ws.(*lockedWriteSyncer);?ok?{????????//?no?need?to?layer?on?another?lock????????return?ws????}????return?&lockedWriteSyncer{ws:?ws}}func?(s?*lockedWriteSyncer)?Write(bs?[]byte)?(int,?error)?{????s.Lock()????n,?err?:=?s.ws.Write(bs)????s.Unlock()????return?n,?err}func?(s?*lockedWriteSyncer)?Sync()?error?{????s.Lock()????err?:=?s.ws.Sync()????s.Unlock()????return?err}lockedWriteSyncer定義了sync.Mutex及WriteSyncer屬性,它實現了WriteSyncer接口,它對Write和Sync方法都加了鎖,內部委托的WriteSyncer;Lock方法用于創建lockedWriteSyncer
multiWriteSyncer
zap@v1.16.0/zapcore/write_syncer.go
type?multiWriteSyncer?[]WriteSyncerfunc?NewMultiWriteSyncer(ws?...WriteSyncer)?WriteSyncer?{????if?len(ws)?==?1?{????????return?ws[0]????}????//?Copy?to?protect?against?https://github.com/golang/go/issues/7809????return?multiWriteSyncer(append([]WriteSyncer(nil),?ws...))}func?(ws?multiWriteSyncer)?Write(p?[]byte)?(int,?error)?{????var?writeErr?error????nWritten?:=?0????for?_,?w?:=?range?ws?{????????n,?err?:=?w.Write(p)????????writeErr?=?multierr.Append(writeErr,?err)????????if?nWritten?==?0?&&?n?!=?0?{????????????nWritten?=?n????????}?else?if?n?multiWriteSyncer為[]WriteSyncer類型,它實現了WriteSyncer接口,其Write方法會遍歷multiWriteSyncer挨個執行其w.Write,然后會用multierr.Append(writeErr, err)來包裝err;其Sync方法會遍歷multiWriteSyncer,挨個執行w.Sync(),然后會用multierr.Append(writeErr, err)來包裝err;NewMultiWriteSyncer方法用于創建multiWriteSyncer
CombineWriteSyncers
zap@v1.16.0/writer.go
func?CombineWriteSyncers(writers?...zapcore.WriteSyncer)?zapcore.WriteSyncer?{????if?len(writers)?==?0?{????????return?zapcore.AddSync(ioutil.Discard)????}????return?zapcore.Lock(zapcore.NewMultiWriteSyncer(writers...))}func?Open(paths?...string)?(zapcore.WriteSyncer,?func(),?error)?{????writers,?close,?err?:=?open(paths)????if?err?!=?nil?{????????return?nil,?nil,?err????}????writer?:=?CombineWriteSyncers(writers...)????return?writer,?close,?nil}func?open(paths?[]string)?([]zapcore.WriteSyncer,?func(),?error)?{????writers?:=?make([]zapcore.WriteSyncer,?0,?len(paths))????closers?:=?make([]io.Closer,?0,?len(paths))????close?:=?func()?{????????for?_,?c?:=?range?closers?{????????????c.Close()????????}????}????var?openErr?error????for?_,?path?:=?range?paths?{????????sink,?err?:=?newSink(path)????????if?err?!=?nil?{????????????openErr?=?multierr.Append(openErr,?fmt.Errorf("couldn't?open?sink?%q:?%v",?path,?err))????????????continue????????}????????writers?=?append(writers,?sink)????????closers?=?append(closers,?sink)????}????if?openErr?!=?nil?{????????close()????????return?writers,?nil,?openErr????}????return?writers,?close,?nil}CombineWriteSyncers方法會先使用zapcore.NewMultiWriteSyncer(writers…)創建multiWriteSyncer,在通過Lock創建lockedWriteSyncer;Open方法根據paths創建zapcore.WriteSyncer,最后通過CombineWriteSyncers來創建帶鎖的multiWriteSyncer
Sink
zap@v1.16.0/sink.go
type?Sink?interface?{????zapcore.WriteSyncer????io.Closer}Sink接口內嵌了zapcore.WriteSyncer及io.Closer接口
Closer
/usr/local/go/src/io/io.go
type?Closer?interface?{????Close()?error}Closer接口定義了Close方法
nopCloserSink
type?nopCloserSink?struct{?zapcore.WriteSyncer?}func?(nopCloserSink)?Close()?error?{?return?nil?}nopCloserSink內嵌了zapcore.WriteSyncer,其Close方法為空操作
newSink
zap@v1.16.0/sink.go
var?(????_sinkMutex?????sync.RWMutex????_sinkFactories?map[string]func(*url.URL)?(Sink,?error)?//?keyed?by?scheme)func?init()?{????resetSinkRegistry()}func?resetSinkRegistry()?{????_sinkMutex.Lock()????defer?_sinkMutex.Unlock()????_sinkFactories?=?map[string]func(*url.URL)?(Sink,?error){????????schemeFile:?newFileSink,????}}func?newSink(rawURL?string)?(Sink,?error)?{????u,?err?:=?url.Parse(rawURL)????if?err?!=?nil?{????????return?nil,?fmt.Errorf("can't?parse?%q?as?a?URL:?%v",?rawURL,?err)????}????if?u.Scheme?==?""?{????????u.Scheme?=?schemeFile????}????_sinkMutex.RLock()????factory,?ok?:=?_sinkFactories[u.Scheme]????_sinkMutex.RUnlock()????if?!ok?{????????return?nil,?&errSinkNotFound{u.Scheme}????}????return?factory(u)}newSink方法解析url,然后通過scheme找到對應的factory,調用factory創建Sink;_sinkFactories默認注冊了newFileSink
newFileSink
zap@v1.16.0/sink.go
func?newFileSink(u?*url.URL)?(Sink,?error)?{????if?u.User?!=?nil?{????????return?nil,?fmt.Errorf("user?and?password?not?allowed?with?file?URLs:?got?%v",?u)????}????if?u.Fragment?!=?""?{????????return?nil,?fmt.Errorf("fragments?not?allowed?with?file?URLs:?got?%v",?u)????}????if?u.RawQuery?!=?""?{????????return?nil,?fmt.Errorf("query?parameters?not?allowed?with?file?URLs:?got?%v",?u)????}????//?Error?messages?are?better?if?we?check?hostname?and?port?separately.????if?u.Port()?!=?""?{????????return?nil,?fmt.Errorf("ports?not?allowed?with?file?URLs:?got?%v",?u)????}????if?hn?:=?u.Hostname();?hn?!=?""?&&?hn?!=?"localhost"?{????????return?nil,?fmt.Errorf("file?URLs?must?leave?host?empty?or?use?localhost:?got?%v",?u)????}????switch?u.Path?{????case?"stdout":????????return?nopCloserSink{os.Stdout},?nil????case?"stderr":????????return?nopCloserSink{os.Stderr},?nil????}????return?os.OpenFile(u.Path,?os.O_WRONLY|os.O_APPEND|os.O_CREATE,?0666)}newFileSink針對stdout創建nopCloserSink{os.Stdout},針對stderr創建nopCloserSink{os.Stderr},非以上兩者則返回os.OpenFile(u.Path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666);*os.File擁有Write、Sync、Close方法,實現了Sink接口
實例
func?sinkDemo()?{????sink,?cleanup,?err?:=?zap.Open("stdout",?"/tmp/out1",?"/tmp/out2")????if?err?==?nil?{????????defer?cleanup()????}????sink.Write([]byte("hello"))????sink.Write([]byte("world"))}輸出
helloworld同時/tmp/out1,/tmp/out2也都有輸出
小結
- WriteSyncer內嵌了io.Writer接口,定義了Sync方法;它有lockedWriteSyncer、multiWriteSyncer兩個實現,同時CombineWriteSyncers創建是帶lock的multiWriteSyncer
- Sink接口內嵌了zapcore.WriteSyncer及io.Closer接口;*os.File擁有Write、Sync、Close方法,實現了Sink接口;nopCloserSink內嵌了zapcore.WriteSyncer,其Close方法為空操作;FileSink則是基于文件的sink
- zap.Open先通過newSink創建fileSink的zapcore.WriteSyncer,再通過CombineWriteSyncers將這些fileSink包裝為帶鎖的multiWriteSyncer
doc
- zap
總結
以上是生活随笔為你收集整理的golang byte 转writer_聊聊golang的zap的WriteSyncer的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cron表达式 每隔1个小时_2-1!1
- 下一篇: cas 注销不关闭浏览器异常_如何关闭华