I would like to know the best practice in Go equivalent to C++ functions binding with default params, which may be easiest for the user to see the function params(with linter help).
What do you think will be the most GO style and easiest way to use the test function ?
An example function in C++:
void test(int x, int y=0, color=Color());
Equivalence in Go
1. With multiple signatures:
func test(x int)
func testWithY(x int, y int)
func testWithColor(x int, color Color)
func testWithYColor(x int, y int, color Color)
pro:
cons:
2. With struct parameter:
type testOptions struct {
X int
Y int
color Color
}
func test(opt *testOptions)
// user
test(&testOptions{x: 5})
pro:
cons:
With the help of the module github.com/creasty/defaults, there is a way to set default values (but with the cost of calling reflect in runtime).
type testOptions struct {
X int
Y int `default:"10"`
color Color `default:"{}"`
}
func test(opt *testOptions) *hg.Node {
if err := defaults.Set(opt); err != nil {
panic(err)
}
}
pro:
cons:
P.S.:
I saw the use of variadic parameters ... or/with interface{} but I find it not easy to know which params to use (or maybe there is a way to indicate a params list to the linter).
Either way will work fine, but in Go the functional options pattern might be more idiomatic for implementing such functionality.
It is based on the idea of accepting a variable amount of WithXXX type of functional arguments that extend of modify the behavior of the call.
type Test struct {
X int
Y int
color Color
}
type TestOption func(*Test)
func test(x int, opts ...TestOption) {
p := &Test{
X: x,
Y: 12,
Color: defaultColor,
}
for _, opt := range opts {
opt(p)
}
p.runTest()
}
func main() {
test(12)
test(12, WithY(34))
test(12, WithY(34), WithColor(Color{1, 2, 3}))
}
func WithY(y int) TestOption {
return func(p *Test) {
p.Y = y
}
}
func WithColor(c Color) TestOption {
return func(p *Test) {
p.color = c
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With