Here are 3 more suggestions or techniques:
With an Additional Field
You can add an additional field to tell if the struct has been populated or it is empty. I intentionally named it ready and not empty because the zero value of a bool is false, so if you create a new struct like Session{} its ready field will be automatically false and it will tell you the truth: that the struct is not-yet ready (it's empty).
type Session struct {
ready bool
playerId string
beehive string
timestamp time.Time
}
When you initialize the struct, you have to set ready to true. Your isEmpty() method isn't needed anymore (although you can create one if you want to) because you can just test the ready field itself.
var s Session
if !s.ready {
// do stuff (populate s)
}
Significance of this one additional bool field increases as the struct grows bigger or if it contains fields which are not comparable (e.g. slice, map and function values).
Using the Zero Value of an Existing Field
This is similar to the previous suggestion, but it uses the zero value of an existing field which is considered invalid when the struct is not empty. Usability of this is implementation dependant.
For example if in your example your playerId cannot be the empty string "", you can use it to test if your struct is empty like this:
var s Session
if s.playerId == "" {
// do stuff (populate s, give proper value to playerId)
}
In this case it's worth incorporating this check into an isEmpty() method because this check is implementation dependant:
func (s Session) isEmpty() bool {
return s.playerId == ""
}
And using it:
if s.isEmpty() {
// do stuff (populate s, give proper value to playerId)
}
Use Pointer to your struct
The second suggestion is to use a Pointer to your struct: *Session. Pointers can have nil values, so you can test for it:
var s *Session
if s == nil {
s = new(Session)
// do stuff (populate s)
}