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