可选参数即我们可以设置也可以不设置的参数,如果我们不设置,则会使用默认值。
在JAVA中我们可以用函数重载(overloading)来实现可选参数(如下述代码所示),可以看到如果我们不需要配置A我们可以直接使用doSomething()
,如果我们需要配置A,可以使用doSomething(String a)
public class A{
public void doSomething(){
helper("default-a","default-b","default-c");
}
public void doSomething(String a){
helper(a,"default-b","default-c");
}
public void helper(String a,String b,String c){
//...
}
}
而在javascript(ES6)中,我们可以通过下述方式来达到可选参数的目的,可以看到如果我们不传入参数,那么就会使用默认参数"tigers"
和bears
function animalSentence(animals2="tigers", animals3="bears") {
return `Lions and ${animals2} and ${animals3}! Oh my!`;
}
可选参数允许用户可以直接使用特定方法,而不用在一头雾水的情况下被要求配置一些参数。不过go不直接支持函数重载以及可选参数(optional parameter),不过我们当然可以提供一些work around的办法
使用前
func Dosomething(timeout time.Duration)//如果我不想设置timeout呢?
func Init(optionA string,optionB string,optionC string)//天啊我要设置所有option吗
使用后
func Dosomething()
func DosomethingWithTimeout()
func Init()
func InitWithA(string)
func InitWithB(string)
func InitWithC(string)
优点
可读性强,易于理解内部逻辑
缺点
只能用于少量参数,比方说上述的使用中如果我需要A,B都可选,那么我就需要排列组合出四种函数了
使用前
func Dosomething(timeout time.Duration)//如果我不想设置timeout呢?
func Init(optionA string,optionB string,optionC string)//天啊我要设置所有option吗
使用后
type Option struct{
A string
B string
C string
}
func (o Option) A() string{
if o.A!=""{
return o.A
}
return "default-a"//如果没有设置值则返回默认值
}
...
func Init(op Option){
a:=op.A()
b:=op.B()
}
优点
允许提供默认值
使用前
func Dosomething(timeout time.Duration)//如果我不想设置timeout呢?
func Init(optionA string,optionB string,optionC string)//天啊我要设置所有option吗
使用后
type Option func(*OptionSet)
func New(opts ...Option){
//下面设置默认值
options:=OptionSet{
A:"default-a",
B:"default-b",
C:"default-c",
}
for _,fun:=range opts{
fun(&options)
}
}
//如果我们需要提供option选项,比方说设置A
func WithA(a string) Option{
return func(opt *OptionSet){
opt.A=a
}
}
// 使用的时候
a=New(WithA("abc"))
该方式是被广泛使用的方式,同时也是风格指南所推荐的方式。其优点在于因为用户可以自行定义修改函数,因此可以适用于很多开发者都没有考虑到的用例,常见于中间件中。