grpc压缩编解码
encoding/encoding.go:23
源码分析
压缩接口
type Compressor interface {
Compress(w io.Writer) (io.WriteCloser, error)
Decompress(r io.Reader) (io.Reader, error)
Name() string
}
编码接口
type Codec interface {
Marshal(v interface{}) ([]byte, error)
Unmarshal(data []byte, v interface{}) error
Name() string
}
默认支持protobuf编码组件, gzip压缩组件
从protobuf编码组件看对象池应用
对象池创建, 对象是proto.Buffer{}
```go
var protoBufferPool = &sync.Pool{
New: func() interface{} {
return &cachedProtoBuffer{
Buffer: proto.Buffer{},
lastMarshaledSize: 16,
}
},
}
```
从对象池取出一个protobuf对象, 塞入数据, 调用反序列化, 清空protobuf, 将protobuf对象放回对象池中
```go
func (codec) Unmarshal(data []byte, v interface{}) error {
protoMsg := v.(proto.Message)
protoMsg.Reset()
if pu, ok := protoMsg.(proto.Unmarshaler); ok {
// object can unmarshal itself, no need for buffer
return pu.Unmarshal(data)
}
//从对象池取出一个protobuf对象, 塞入数据, 调用反序列化, 清空protobuf, 将protobuf对象放回对象池中
cb := protoBufferPool.Get().(*cachedProtoBuffer)
cb.SetBuf(data)
err := cb.Unmarshal(protoMsg)
cb.SetBuf(nil)
protoBufferPool.Put(cb)
return err
}
```
从对象池取出一个protobuf对象, 序列化对象得到字节码, 清空protobuf, 将protobuf对象放回对象池中
```go
func (codec) Marshal(v interface{}) ([]byte, error) {
if pm, ok := v.(proto.Marshaler); ok {
// object can marshal itself, no need for buffer
return pm.Marshal()
}
cb := protoBufferPool.Get().(*cachedProtoBuffer)
protoMsg := v.(proto.Message)
newSlice := make([]byte, 0, cb.lastMarshaledSize)
cb.SetBuf(newSlice)
cb.Reset()
if err := cb.Marshal(protoMsg); err != nil {
return nil, err
}
out := cb.Bytes()
cb.lastMarshaledSize = capToMaxInt32(len(out))
// put back buffer and lose the ref to the slice
cb.SetBuf(nil)
protoBufferPool.Put(cb)
return out, err
}
```
这里grpc关于编解码的对象池应用, 看起来代码多, 其实就是go src对象池的应用
对象池使用步骤
- 创建对象池
- 从池中取出对象Get()
- 使用对象处理自己的逻辑
- 把对象放入池中Put()