6

golang protobuf序列化分析

 3 years ago
source link: https://studygolang.com/articles/32403
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

golang protobuf序列化分析

Lynn_Yuan · 大约5小时之前 · 23 次点击 · 预计阅读时间 4 分钟 · 不到1分钟之前 开始浏览    

  1. data.proto
    message ColumnarValue {
    uint32 id= 1;
    int32 typ = 2;
    repeated bytes values = 3;
    }

    data.go.proto

    type ColumnarValue struct {
    Id   uint32   `protobuf:"varint,1,opt,name=id,json=id,proto3" json:"id,omitempty"`
    Typ int32    `protobuf:"varint,2,opt,name=typ,json=typ,proto3" json:"typ,omitempty"`
    Values  [][]byte `protobuf:"bytes,3,rep,name=values,proto3" json:"values,omitempty"`
    }
  2. 序列化
    func (m *ColumnarValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
    b = b[:cap(b)]
    n, err := m.MarshalTo(b)
    if err != nil {
        return nil, err
    }
    return b[:n], nil
    }
func (m *ColumnarValue) MarshalTo(dAtA []byte) (int, error) {
    var i int
    _ = i
    var l int
    _ = l
    if m.Id != 0 {
        dAtA[i] = 0x8
        i++
        i = encodeVarintData(dAtA, i, uint64(m.Id))
    }
    if m.Typ != 0 {
        dAtA[i] = 0x10
        i++
        i = encodeVarintData(dAtA, i, uint64(m.Typ))
    }
    if len(m.Values) > 0 {  // [][]byte序列化
        for _, b := range m.Values {
            dAtA[i] = 0x1a
            i++
            i = encodeVarintData(dAtA, i, uint64(len(b)))  // 对byte Slice的长度(int值)编码
            i += copy(dAtA[i:], b)              // 直接复制b(bytes)切片
        }
    }
    return i, nil
}

编码(slice长度)

func encodeVarintData(dAtA []byte, offset int, v uint64) int {
    for v >= 1<<7 {
        dAtA[offset] = uint8(v&0x7f | 0x80)
        v >>= 7
        offset++
    }
    dAtA[offset] = uint8(v)
    return offset + 1
}
  1. func (m *VecValue) XXX_Unmarshal(b []byte) error {
    return m.Unmarshal(b)
    }
    func (m *VecValue) Unmarshal(dAtA []byte) error {
    l := len(dAtA)
    iNdEx := 0
    for iNdEx < l {
        preIndex := iNdEx
        var wire uint64
        for shift := uint(0); ; shift += 7 {
            if shift >= 64 {
                return ErrIntOverflowData
            }
            if iNdEx >= l {
                return io.ErrUnexpectedEOF
            }
            b := dAtA[iNdEx]
            iNdEx++
            wire |= (uint64(b) & 0x7F) << shift
            if b < 0x80 {
                break
            }
        }
        fieldNum := int32(wire >> 3)
        wireType := int(wire & 0x7)
        if wireType == 4 {
            return fmt.Errorf("proto: VecValue: wiretype end group for non-group")
        }
        if fieldNum <= 0 {
            return fmt.Errorf("proto: VecValue: illegal tag %d (wire type %d)", fieldNum, wire)
        }
        switch fieldNum {
        case 1:
            if wireType != 0 {
                return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType)
            }
            m.Id = 0
            for shift := uint(0); ; shift += 7 {
                if shift >= 64 {
                    return ErrIntOverflowData
                }
                if iNdEx >= l {
                    return io.ErrUnexpectedEOF
                }
                b := dAtA[iNdEx]
                iNdEx++
                m.Id |= (uint32(b) & 0x7F) << shift
                if b < 0x80 {
                    break
                }
            }
        case 2:
            if wireType != 0 {
                return fmt.Errorf("proto: wrong wireType = %d for field Typ", wireType)
            }
            m.Typ = 0
            for shift := uint(0); ; shift += 7 {
                if shift >= 64 {
                    return ErrIntOverflowData
                }
                if iNdEx >= l {
                    return io.ErrUnexpectedEOF
                }
                b := dAtA[iNdEx]
                iNdEx++
                m.Typ |= (int32(b) & 0x7F) << shift
                if b < 0x80 {
                    break
                }
            }
        case 3:
            if wireType != 2 {
                return fmt.Errorf("proto: wrong wireType = %d for field Values", wireType)
            }
            var byteLen int
            for shift := uint(0); ; shift += 7 {
                if shift >= 64 {
                    return ErrIntOverflowData
                }
                if iNdEx >= l {
                    return io.ErrUnexpectedEOF
                }
                b := dAtA[iNdEx]
                iNdEx++
                byteLen |= (int(b) & 0x7F) << shift
                if b < 0x80 {
                    break
                }
            }
            if byteLen < 0 {
                return ErrInvalidLengthData
            }
            postIndex := iNdEx + byteLen
            if postIndex > l {
                return io.ErrUnexpectedEOF
            }
            m.Values = append(m.Values, make([]byte, postIndex-iNdEx))
            copy(m.Values[len(m.Values)-1], dAtA[iNdEx:postIndex])  // 直接复制dAtA切片中指定内容, go层内部 内存复制
            iNdEx = postIndex
        default:
            iNdEx = preIndex
            skippy, err := skipData(dAtA[iNdEx:])
            if err != nil {
                return err
            }
            if skippy < 0 {
                return ErrInvalidLengthData
            }
            if (iNdEx + skippy) > l {
                return io.ErrUnexpectedEOF
            }
            iNdEx += skippy
        }
    }
    
    if iNdEx > l {
        return io.ErrUnexpectedEOF
    }
    return nil
    }

有疑问加站长微信联系(非本文作者)

280

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:1006366459


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK