Reputation: 48761
If I have a function where the last argument is optional, is it an appropriate practice to use ...
to allow the argument to be optional, or is it considered bad form?
Example:
func Foo(s ...string) {
switch len(s) {
case 0:
fmt.Println("You didn't pass an argument")
case 1:
fallthrough
default:
fmt.Printf("You passed %s\n", s[0])
}
}
Foo("bar") // "You passed bar"
Foo() // "You didn't pass an argument"
Foo("bar", "baz") // "You passed bar"
In this example, I don't care if too many arguments were passed, but I could handle that in the default:
case when needed.
Upvotes: 2
Views: 1167
Reputation: 17655
It's all depends on your projects requirements, if your project is in a situation like this, then there is not any bad form
The optional argument facility is provided only for this kind of situation.
Upvotes: 0
Reputation: 1473
If you really need optional arguments (and as you can see from the Go stdlib, it is rare), the idiomatic way is to define a struct with fields for each of the optional arguments, and then callers can pass a struct literal with the fields they want filled in.
More common is to provide alternative function or methods, when it is only one or two "optional" arguments, which should be most of the time.
Optional arguments in languages like Python often mean that the API grows and grows until functions and methods have more arguments than anyone can remember, and it is never clear how various combinations of arguments interact (and they are even less tested).
Forcing you to define explicit functions and methods for the various combinations of parameters requires more thought up front about your API, but makes it much more usable and maintainable in the long term.
Upvotes: 12
Reputation: 91193
I would not recommend this. There are different problems with (ab)using variadic parameters for passing optional arguments. Most important of them is probably that the form of the last arg ...T)
allows for only one type. For more than one optional parameter with more than one type one can use ...interface{}
but that incurs unnecessary run time (un)boxing costs and lacks any (usefull) compile time type checking.
Another possible argument against is that I don't think you'll find an example/precedent for this anywhere in the standard library, which is considered an informal Go coding style guide by some.
Upvotes: 6