The way I program in Go is different from the way I program in, e.g., C# with its new nullability features where you only need to put a ?
after a type name to make it optional. The way I indicate that something is optional in Go depends on a lot of context. For example, for functions whose parameters are optional, if only one or two parameters are optional, I usually make separate functions (e.g. instead of NewThing
, have also NewThingWithContext
, etc.). If more configurability is needed than that, I use “functional options”:
So instead of:
package mypkg
func NewThing(timeout *time.Duration) (*Thing, error) {
// ...
}
thingA, err := mypkg.NewThing(nil)
d := 5 * time.Second
thingB, err := mypkg.NewThing(&d)
I do something more like:
package mypkg
type ThingOption func(t *Thing) error
func NewThing(options ...ThingOption) (*Thing, error) {
// ...
}
myThing, err := mypkg.NewThing(
mypkg.ThingTimeout(5 * time.Second),
)
It’s more verbose, but I like the pattern.
If you mean that struct field values are optional, depending on the value’s type, I might just use a sentinel value, e.g.:
type MyStruct struct {
// Timeout for an operation. If 0, no timeout is set.
Timeout time.Duration
}
Or if it’s very common to use this optional type throughout my package, I might define an optional type for it:
type OptionalTimeout struct {
// HasDuration is set when the Duration field's value should be
// respected. A Duration of 0 when HasDuration is true indicates
// that the operation should be aborted immediately
HasDuration bool
Duration time.Duration
}
If you mean some other context other than struct fields or function parameters, I’d need to see the specifics to describe what I would do in that situation.