sequence
This paper mainly studies golang’s ZAP buffer
buffer
[email protected] / 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) }Copy the code
Buffer defines the []byte and Pool attributes, AppendByte, AppendString, AppendInt, AppendTime, AppendUint, AppendBool, AppendFloat, String, Reset, Write, TrimNewline, and Free methods are provided
pool
[email protected] / 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)
}
Copy the code
Pool *sync.Pool NewPool creates sync.Pool, New Buffer, _size 1024 (1KB) by default. Its Get method gets the buffer from the pool, and its PUT method returns the buffer to the pool. Since the buffer may not be reset on return, it will be reset before returning each time it gets
bufferpool
[email protected] / 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
)
Copy the code
The bufferPool package creates a global _pool and defines Get func
FullPath
[email protected] / 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 }Copy the code
The FullPath method uses a bufferPool to create a caller
newJSONEncoder
[email protected] / zapcore json_encoder. Go
func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
return &jsonEncoder{
EncoderConfig: &cfg,
buf: bufferpool.Get(),
spaced: spaced,
}
}
Copy the code
NewJSONEncoder uses bufferpool.get () to Get the buffer, and then creates the jsonEncoder
The instance
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() }Copy the code
The output
V foo 42 42 true 3.14 foo 2000-01-02T03:04:05zCopy the code
summary
Buffer defines the []byte and Pool attributes, AppendByte, AppendString, AppendInt, AppendTime, AppendUint, AppendBool, AppendFloat, String, Reset, Write, TrimNewline, and Free methods are provided ; Pool *sync.Pool NewPool creates sync.Pool, New Buffer, _size 1024 (1KB) by default. Its Get method gets the buffer from the pool, and its PUT method returns the buffer to the pool. Since the buffer may not be reset on return, it will be reset before returning each time it gets
doc
- zap