日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

golang byte 转writer_聊聊golang的zap的WriteSyncer

發布時間:2024/1/23 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。