英文:
How to ignore zero value in struct in Google Datastore for Golang?
问题
我正在尝试使用Google Datastore通过Go语言存储数据。由于EndDate
是可选字段,并且不想在该字段中存储零值。如果我为时间字段创建一个指针,Google Datastore将发送错误消息 - datastore: unsupported struct field type: *time.Time
如何忽略结构体中的零值字段?
type Event struct {
StartDate *time.Time `datastore:"start_date,noindex" json:"startDate"`
EndDate *time.Time `datastore:"end_date,noindex" json:"endDate"`
}
英文:
I am trying to use Google Datastore to store data by Go. Since the EndDate
is optional field, and don't want to store zero value in that field. If I make a pointer for time field, Google Datastore will send an error message - datastore: unsupported struct field type: *time.Time
How can I ignore zero value field in struct?
type Event struct {
StartDate time.Time `datastore:"start_date,noindex" json:"startDate"`
EndDate time.Time `datastore:"end_date,noindex" json:"endDate"`
}
答案1
得分: 2
默认的保存机制不处理可选字段。一个字段要么始终保存,要么从不保存。不存在“只有在其值不等于某个值时才保存”的情况。
“可选保存属性”被视为自定义行为、自定义保存机制,因此必须手动实现。Go语言实现这一点的方式是在结构体上实现PropertyLoadSaver
接口。这里我介绍两种不同的实现方法:
手动保存字段
下面是一个示例,演示如何通过手动保存字段(如果EndDate
为零值,则排除它):
type Event struct {
StartDate time.Time `datastore:"start_date,noindex" json:"startDate"`
EndDate time.Time `datastore:"end_date,noindex" json:"endDate"`
}
func (e *Event) Save(c chan<- datastore.Property) error {
defer close(c)
// 始终保存 StartDate:
c <- datastore.Property{Name:"start_date", Value:e.StartDate, NoIndex: true}
// 仅在 EndDate 不是零值时保存:
if !e.EndDate.IsZero() {
c <- datastore.Property{Name:"end_date", Value:e.EndDate, NoIndex: true}
}
return nil
}
func (e *Event) Load(c chan<- datastore.Property) error {
// 加载时不需要更改,调用默认实现:
return datastore.LoadStruct(e, c)
}
使用另一个结构体
这是另一种使用另一个结构体的方法。Load()
实现始终相同,只有 Save()
不同:
func (e *Event) Save(c chan<- datastore.Property) error {
if !e.EndDate.IsZero() {
// 如果 EndDate 不是零值,按通常方式保存:
return datastore.SaveStruct(e, c)
}
// 否则,我们需要一个没有 EndDate 字段的结构体:
s := struct{ StartDate time.Time `datastore:"start_date,noindex"` }{e.StartDate}
// 现在可以使用默认的保存机制保存它:
return datastore.SaveStruct(&s, c)
}
英文:
The default saving mechanism does not handle optional fields. A field is either saved all the time, or never. There is no such thing as "only save if it's value does not equal to something".
The "optionally saved property" is considered a custom behavior, a custom saving mechanism, and as such, it has to be implemented manually. Go's way to do this is to implement the PropertyLoadSaver
interface on your struct. Here I present 2 different methods to achieve that:
Manually saving fields
Here is an example how to do it by manually saving the fields (and excluding EndDate
if it is the zero value):
type Event struct {
StartDate time.Time `datastore:"start_date,noindex" json:"startDate"`
EndDate time.Time `datastore:"end_date,noindex" json:"endDate"`
}
func (e *Event) Save(c chan<- datastore.Property) error {
defer close(c)
// Always save StartDate:
c <- datastore.Property{Name:"start_date", Value:e.StartDate, NoIndex: true}
// Only save EndDate if not zero value:
if !e.EndDate.IsZero() {
c <- datastore.Property{Name:"end_date", Value:e.EndDate, NoIndex: true}
}
return nil
}
func (e *Event) Load(c chan<- datastore.Property) error {
// No change required in loading, call default implementation:
return datastore.LoadStruct(e, c)
}
With another struct
Here's another way using another struct. The Load()
implementation is always the same, only Save()
differs:
func (e *Event) Save(c chan<- datastore.Property) error {
if !e.EndDate.IsZero() {
// If EndDate is not zero, save as usual:
return datastore.SaveStruct(e, c)
}
// Else we need a struct without the EndDate field:
s := struct{ StartDate time.Time `datastore:"start_date,noindex"` }{e.StartDate}
// Which now can be saved using the default saving mechanism:
return datastore.SaveStruct(&s, c)
}
答案2
得分: 1
在字段标签中使用omitempty。
从文档中可以看到:https://golang.org/pkg/encoding/json/
结构体值被编码为JSON对象。除非满足以下条件,否则每个导出的结构体字段都成为对象的成员:
- 字段的标签是“-”,或者
- 字段为空,并且其标签指定了“omitempty”选项。
示例:Field int
json:"myName,omitempty"
英文:
Use omitempty in the field tags.
From the docs: https://golang.org/pkg/encoding/json/
> Struct values encode as JSON objects. Each exported struct field
> becomes a member of the object unless
>
> - the field's tag is "-", or
> - the field is empty and its tag specifies the "omitempty" option.
>
> Field int json:"myName,omitempty"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论