为了账号安全,请及时绑定邮箱和手机立即绑定

MarshalBinary time.Time:预测其字节大小

MarshalBinary time.Time:预测其字节大小

Go
慕沐林林 2022-05-18 16:47:24
可以预测大小 time.Time.MarshalBinary() 返回的缓冲区 - 以协助其他自定义类型的二进制解组。尝试为我的类型编写一个紧凑的 BinaryMarshaler(即避免存储不必要的大小标记):type Item struct {    t time.Time    m *pb.Device // implements proto.Message - so use proto.Marshal(...) to Marshal}这两个字段都有 BinaryMarshaler,所以这应该很容易。第一遍,是将两个编组附加[]bytes在一起(时间第一,proto.Message 第二)。但是如何Unmarshal,因为time.Time.UnmarshalBinary不指示消耗了多少字节 - 那么应该使用什么偏移量来开始proto.Message解组?检查时间源建议time.Time.MarshalBinary()将始终返回 15 个字节(第一个字节包含 的算法版本1)。1.2.2从 go 版本到今天(1.14),这似乎都是正确的。因此,可以计算 a 消耗的字节数time.UnmarshalBinary以协助自定义BinaryUnmarshalers- 并避免硬编码假设,例如:func (i *Item) UnmarshalBinary(b []byte) error {    const (        timeV     = 1        timeV1Len = 15    )    if len(b) == 0 {        *i = Item{} // no data - set to zero value        return nil    }    if b[0] != timeV {        return fmt.Errorf("time.Time binary marshaled at unsupported version %d (expected version %d)", b[0], timeV)    }    if len(b) < timeV1Len {        return fmt.Errorf("data too short: should be >= %d bytes, got %d byte(s)", timeV1Len, len(b))    }    if err = i.t.UnmarshalBinary(b[:timeV1Len]); err != nil {        return err    }    if len(b[timeV1Len:]) == 0 {        i.m = nil // no more data, so set Message nil        return nil    }    i.m = &pb.Device{}    return proto.Unmarshal(b[timeV1Len:], i.m)}
查看完整描述

1 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

据我所知,输出的大小MarshalBinary不受Go 1 Compatibility Promise的约束:

未指定的行为。Go 规范试图明确该语言的大多数属性,但有些方面未定义。依赖于这种未指定行为的程序可能会在未来的版本中中断。

Time.MarshalBinary没有指定其输出的大小,因此它会被视为“未指定的行为”。


查看完整回答
反对 回复 2022-05-18
  • 1 回答
  • 0 关注
  • 169 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号