美文网首页
聊聊golang的zap的buffer

聊聊golang的zap的buffer

作者: go4it | 来源:发表于2020-12-14 23:23 被阅读0次

    本文主要研究一下golang的zap的buffer

    buffer

    zap@v1.16.0/buffer/buffer.go

    package buffer // import "go.uber.org/zap/buffer"
    
    import (
        "strconv"
        "time"
    )
    
    const _size = 1024 // by default, create 1 KiB buffers
    
    // Buffer is a thin wrapper around a byte slice. It's intended to be pooled, so
    // the only way to construct one is via a Pool.
    type Buffer struct {
        bs   []byte
        pool Pool
    }
    
    // AppendByte writes a single byte to the Buffer.
    func (b *Buffer) AppendByte(v byte) {
        b.bs = append(b.bs, v)
    }
    
    // AppendString writes a string to the Buffer.
    func (b *Buffer) AppendString(s string) {
        b.bs = append(b.bs, s...)
    }
    
    // AppendInt appends an integer to the underlying buffer (assuming base 10).
    func (b *Buffer) AppendInt(i int64) {
        b.bs = strconv.AppendInt(b.bs, i, 10)
    }
    
    // AppendTime appends the time formatted using the specified layout.
    func (b *Buffer) AppendTime(t time.Time, layout string) {
        b.bs = t.AppendFormat(b.bs, layout)
    }
    
    // AppendUint appends an unsigned integer to the underlying buffer (assuming
    // base 10).
    func (b *Buffer) AppendUint(i uint64) {
        b.bs = strconv.AppendUint(b.bs, i, 10)
    }
    
    // AppendBool appends a bool to the underlying buffer.
    func (b *Buffer) AppendBool(v bool) {
        b.bs = strconv.AppendBool(b.bs, v)
    }
    
    // AppendFloat appends a float to the underlying buffer. It doesn't quote NaN
    // or +/- Inf.
    func (b *Buffer) AppendFloat(f float64, bitSize int) {
        b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize)
    }
    
    // Len returns the length of the underlying byte slice.
    func (b *Buffer) Len() int {
        return len(b.bs)
    }
    
    // Cap returns the capacity of the underlying byte slice.
    func (b *Buffer) Cap() int {
        return cap(b.bs)
    }
    
    // Bytes returns a mutable reference to the underlying byte slice.
    func (b *Buffer) Bytes() []byte {
        return b.bs
    }
    
    // String returns a string copy of the underlying byte slice.
    func (b *Buffer) String() string {
        return string(b.bs)
    }
    
    // Reset resets the underlying byte slice. Subsequent writes re-use the slice's
    // backing array.
    func (b *Buffer) Reset() {
        b.bs = b.bs[:0]
    }
    
    // Write implements io.Writer.
    func (b *Buffer) Write(bs []byte) (int, error) {
        b.bs = append(b.bs, bs...)
        return len(bs), nil
    }
    
    // TrimNewline trims any final "\n" byte from the end of the buffer.
    func (b *Buffer) TrimNewline() {
        if i := len(b.bs) - 1; i >= 0 {
            if b.bs[i] == '\n' {
                b.bs = b.bs[:i]
            }
        }
    }
    
    // Free returns the Buffer to its Pool.
    //
    // Callers must not retain references to the Buffer after calling Free.
    func (b *Buffer) Free() {
        b.pool.put(b)
    }
    

    Buffer定义了[]byte及Pool属性,它提供了AppendByte、AppendString、AppendInt、AppendTime、AppendUint、AppendBool、AppendFloat、String、Reset、Write、TrimNewline、Free方法

    pool

    zap@v1.16.0/buffer/pool.go

    package buffer
    
    import "sync"
    
    // A Pool is a type-safe wrapper around a sync.Pool.
    type Pool struct {
        p *sync.Pool
    }
    
    // NewPool constructs a new Pool.
    func NewPool() Pool {
        return Pool{p: &sync.Pool{
            New: func() interface{} {
                return &Buffer{bs: make([]byte, 0, _size)}
            },
        }}
    }
    
    // Get retrieves a Buffer from the pool, creating one if necessary.
    func (p Pool) Get() *Buffer {
        buf := p.p.Get().(*Buffer)
        buf.Reset()
        buf.pool = p
        return buf
    }
    
    func (p Pool) put(buf *Buffer) {
        p.p.Put(buf)
    }
    

    Pool定义了*sync.Pool属性,其NewPool方法创建sync.Pool,New方法为创建Buffer,_size默认为1024即1KB;其Get方法从pool获取buffer,其put方法用于将buffer归还到pool;由于归还时buffer可能没有reset,所以每次Get的时候都会先Reset一下再返回

    bufferpool

    zap@v1.16.0/internal/bufferpool/bufferpool.go

    package bufferpool
    
    import "go.uber.org/zap/buffer"
    
    var (
        _pool = buffer.NewPool()
        // Get retrieves a buffer from the pool, creating one if necessary.
        Get = _pool.Get
    )
    

    bufferpool包创建了一个全局的_pool,并定义了Get func

    FullPath

    zap@v1.16.0/zapcore/entry.go

    func (ec EntryCaller) FullPath() string {
        if !ec.Defined {
            return "undefined"
        }
        buf := bufferpool.Get()
        buf.AppendString(ec.File)
        buf.AppendByte(':')
        buf.AppendInt(int64(ec.Line))
        caller := buf.String()
        buf.Free()
        return caller
    }
    

    FullPath方法使用bufferpool来创建caller

    newJSONEncoder

    zap@v1.16.0/zapcore/json_encoder.go

    func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
        return &jsonEncoder{
            EncoderConfig: &cfg,
            buf:           bufferpool.Get(),
            spaced:        spaced,
        }
    }
    

    newJSONEncoder使用bufferpool.Get()来获取buffer,然后创建jsonEncoder

    实例

    func bufferDemo() {
        buf := buffer.NewPool().Get()
        buf.AppendByte('v')
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.AppendString("foo")
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.AppendInt(42)
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.AppendUint(42)
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.AppendBool(true)
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.AppendFloat(3.14, 32)
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.Write([]byte("foo"))
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.AppendTime(time.Date(2000, 1, 2, 3, 4, 5, 6, time.UTC), time.RFC3339)
        fmt.Println(buf.String())
        buf.Reset()
    
        buf.Free()
    }
    

    输出

    v
    foo
    42
    42
    true
    3.14
    foo
    2000-01-02T03:04:05Z
    

    小结

    Buffer定义了[]byte及Pool属性,它提供了AppendByte、AppendString、AppendInt、AppendTime、AppendUint、AppendBool、AppendFloat、String、Reset、Write、TrimNewline、Free方法;Pool定义了*sync.Pool属性,其NewPool方法创建sync.Pool,New方法为创建Buffer,_size默认为1024即1KB;其Get方法从pool获取buffer,其put方法用于将buffer归还到pool;由于归还时buffer可能没有reset,所以每次Get的时候都会先Reset一下再返回

    doc

    相关文章

      网友评论

          本文标题:聊聊golang的zap的buffer

          本文链接:https://www.haomeiwen.com/subject/ujqigktx.html