如何在Golang中使用`omitempty`与protobuf的Timestamp结构体一起使用。

huangapple go评论84阅读模式
英文:

How to use `omitempty` with protobuf Timestamp in Golang

问题

我在我的结构体上有一个可选字段叫做ExpireTime。它的类型是time.Time,并且有一个json:"expire_time,omitempty"的标签,表示当它为空时不发送该字段。这部分工作得非常好。

当我想通过GRPC使用同样的字段时,将其转换为protobuf时间戳格式时遇到了问题。

type Timestamp struct {

	// 表示自Unix纪元以来的UTC时间的秒数
	// 1970-01-01T00:00:00Z。必须在0001-01-01T00:00:00Z到
	// 9999-12-31T23:59:59Z之间(包括边界)。
	Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
	// 非负的纳秒分辨率的秒的小数部分。具有负秒值的小数部分仍然必须具有非负的纳秒值,
	// 以便按时间向前计数。必须在0到999,999,999之间(包括边界)。
	Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
	// 包含已过滤或未导出的字段
}
ExpireTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"`

问题在于一个空的time.Time{}对象将被转换为一个负的seconds值,对应于0001-01-01T00:00:00Z。在这种情况下,omitEmpty标志将不会被应用,因为该值并没有被置零。我应该怎么做才能在字段实际为空时省略它呢?谢谢!

英文:

I have an optional field on my struct called ExpireTime. It has a time.Time type and a json:"expire_time,omitempty" tag to not send it, when it is empty. This part works perfectly fine.

When I want to use the same field via GRPC, I run into an issue when converting it to the protobuf timestamp format.

type Timestamp struct {

	// Represents seconds of UTC time since Unix epoch
	// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
	// 9999-12-31T23:59:59Z inclusive.
	Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
	// Non-negative fractions of a second at nanosecond resolution. Negative
	// second values with fractions must still have non-negative nanos values
	// that count forward in time. Must be from 0 to 999,999,999
	// inclusive.
	Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
	// contains filtered or unexported fields
}
ExpireTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"`

The issue is that an empty time.Time{} object will be converted to a negative seconds value corresponding to 0001-01-01T00:00:00Z. Having the omitEmpty flag will not be applied in this case as the value is not zeroed out. What could I do to omit this field, when it is actually empty? Thanks!

答案1

得分: 2

根据你的要求,以下是翻译好的内容:

正如你所说,time.Time{} 转换为 0001-01-01T00:00:00Z;这是按预期工作的。请注意,在相反的方向转换时也需要小心(零值的 TimeStamp 将变为 1970-01-01T00:00:00Z)。

然而,通常 Timestamp 将作为消息的一部分,例如:

message MyMessage{
   google.protobuf.Timestamp  comm_time = 1;
}

通过 protoc 运行这段代码将得到类似以下的结果:

type MyMessage struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	CommTime *timestamppb.Timestamp `protobuf:"bytes, 1,opt,name=comm_time,json=commTime,proto3" json:"comm_time,omitempty"`
}

这意味着你可以通过 CommTime=nil 来实现你想要的结果,例如:

sourceTime := time.Time{}  // 你想要编码的时间
var commTime *timestamp.Timestamp
if !sourceTime.IsZero() {
		commTime = timestamppb.New(sourceTime)
}

msg := MyMessage{
   CommTime: commTime,
}
英文:

As you say time.Time{} converts to 0001-01-01T00:00:00Z; this is working as intended. Note that you also need to be careful converting in the opposite direction (a zero TimeStamp will become 1970-01-01T00:00:00Z).

However generally the Timestamp will be part of a message, for example:

message MyMessage{
   google.protobuf.Timestamp  comm_time = 1;
}

Running this through protoc will result in something like:

type MyMessage struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	CommTime *timestamppb.Timestamp `protobuf:"bytes, 1,opt,name=comm_time,json=commTime,proto3" json:"comm_time,omitempty"`
}

This means you should be able to achieve the result you are looking for with CommTime=nil; e.g.

sourceTime := time.Time{}  // Whatever time you want to encode
var commTime *timestamp.Timestamp
if !sourceTime.IsZero() {
		commTime = timestamppb.New(sourceTime)
}

msg := MyMessage{
   CommTime: commTime,
}

huangapple
  • 本文由 发表于 2022年2月11日 20:59:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/71080522.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定