Opinions on Go struct type
September 08, 2020When I create a new go struct, I organize it around serialization and usability.
package main
import (
"encoding/json"
"errors"
"fmt"
"net/url"
)
type Proxy struct {
URL *url.URL `json:"url"`
runs uint64
}
func NewProxy(u *url.URL) (*Proxy, error) {
if u == nil {
return nil, errors.New("missing url")
}
return &Proxy{
URL: u,
// runs is a runtime counter and can start at 0
}, nil
}
func main() {
u, _ := url.Parse("http://example.com")
ms, _ := NewProxy(u)
bs, _ := json.Marshal(ms)
fmt.Println(string(bs))
}
My rules are simple:
- Export fields necessary to surviving serialization.
- Don't export runtime fields, like mutexes and counters.
- Make sure your zero-value means something. Counters start at zero, limits of zero are unlimited, etc.
- Decide whether to use pointer or value semantics on your functions, and stick to one.(Large structs are probably better of with pointer semantics)
- If construction is nontrivial, provide a function that gets it right.