Documentation ¶
Overview ¶
optioner is a tool to generate functional options. Intended to be used with go generate; see the invocation in example/example.go.
To learn about functional options, see: http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html
This code was adapted from the stringer cmd (golang.org/x/tools/cmd/stringer/).
optioner will generate a file with code of the form:
// N sets a value for instances of type Example. func N(o int) optExample { return func(t *Example) optExample { previous := t.N t.N = o return N(previous) } }
The file is created in the package where the code is generated.
optioner will create options for all the fields in the struct except those that include the tag `opt:"-"`.
For example, given this snippet,
package example //go:generate optioner -type Example type Example struct { N int FSlice []float64 `json:"float_slice"` Map map[string]int Name string `opt:"-" json:"name"` ff func(int) int } func NewExample(name string, options ...optExample) *Example { // Set required values and initialize optional fields with default values. ex := &Example{ Name: name, N: 10, FSlice: make([]float64, 0, 100), Map: make(map[string]int), ff: func(n int) int { return n }, } // Set options. ex.Option(options...) }
go generate will generate option functions for fields N, FSlice, Map, and ff. Your package users can now set options as follows:
myFunc := func(n int) int {return 2 * n} ex := example.NewExample("test", example.N(22), example.Ff(myFunc))
the new struct "ex" will use default values for "FSlice" and "Map", and custom values for "N" and "ff". Note that the argument "name" in NewExample() is required. For this reason the struct field "name" is excluded using a tag.
To temporarily modify a value, do the following:
prev := ex.Option(N(5)) // previous value is stored in prev. // do something... ex.Option(prev) // restores the previous value.
struct fields don't need to be exported, however, the corresponding option will be exported by capitalizing the first letter. Documentation for options is auto-generated in the source file to make it available to package users in godoc format.
It is possible to create options for various types in the same package by using various annotations
//go:generate optioner -type Type1 //go:generate optioner -type Type2
However, to keep function names short, there is no namespaces so you must use different names for different option functions in the same package.