Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty or not required struct fields

Tags:

go

mgo

I have two structs that represent models that will be inserted into a mongodb database. One struct (Investment) has the other struct (Group) as one of its fields.

type Group struct {     Base     Name string `json:"name" bson"name"` }  type Investment struct {     Base     Symbol string `json:"symbol" bson:"symbol" binding:"required"`     Group  Group  `json:"group" bson:"group"`     Fields bson.M `json:"fields" bson:"fields"` } 

The problem I'm having is that in the Investment model, Group is not required. If there is no group, I think its better for it to not be inserted in the db. Whats the best way to handle a db model such as this in Go?

like image 691
msecret Avatar asked Jun 14 '14 04:06

msecret


People also ask

How do you know if a struct field is empty?

In general the best advice is to make use of the zero value. Create structures so that zero values of false are useful, rather than a pain. This is not always possible, so changing the types of the fields in the Foo struct to be pointers will allow you to check the 3 cases you are after.

Can you have an empty struct?

An empty structIt occupies zero bytes of storage. As the empty struct consumes zero bytes, it follows that it needs no padding. Thus a struct comprised of empty structs also consumes no storage.

What does an empty struct mean?

— A structure or union is defined without any named members (including those specified indirectly via anonymous structures and unions) (6.7.

How do you declare an empty struct in Golang?

An empty struct is a struct type without fields struct{} . The cool thing about an empty structure is that it occupies zero bytes of storage. You can find an accurate description about the actual mechanism inside the golang compiler in this post by Dave Chaney.


1 Answers

tl;dr: Use ,omitempty, and if you need to worry about the difference between a zero value and null/not specified, do what the GitHub API does and use a pointer.


Both json and bson support the ,omitempty tag. For json, "empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero" (json docs). For bson, ,omitempty means "Only include the field if it's not set to the zero value for the type or to empty slices or maps", and zero values include empty strings and nil pointers (bson docs).

So if you really need a Group struct, you can put a *Group in instead, and it won't be stored when the pointer is nil. If Investment only needs to hold the group's name, it's even simpler: "" as group name keeps a group key from being stored.

bson defaults to using the lowercased field name already so you can omit that from the struct tag when they match. json will default to the Capitalized name, so specify the lowercase name in a tag if you need lowercase.

So, best case, maybe you can just use:

type Investment struct {     Base     Symbol string `json:"symbol" binding:"required"`     Group string  `json:"group,omitempty" bson:",omitempty"`     Fields bson.M `json:"fields"` } 

If you ever run into fields where the zero value for the type ("", 0, false, etc.) is distinct from "not specified", you can do what the GitHub API does and put pointers in your structures--essentially an extension of the *Group trick.

like image 159
twotwotwo Avatar answered Oct 04 '22 21:10

twotwotwo