可选参数?

可以去有可选参数? 或者我可以定义两个具有相同名称和不同数量参数的函数吗?

Go没有可选参数, 也不支持方法重载 :

如果不需要进行types匹配,方法调度也会简化。 对其他语言的使用经验告诉我们,使用同一名称但签名不同的多种方法偶尔有用,但在实践中也可能令人困惑和脆弱。 只与名称匹配并要求types一致性是Gotypes系统中一个重要的简化决策。

您可以使用包含参数的结构:

 type Params struct { a, b, c int } func doIt(p Params) int { return pa + pb + pc } // you can call it without specifying all parameters doIt(Params{a: 1, c: 9}) 

实现类似可选参数的好方法是使用可变参数。 该函数实际上接收到您指定的任何types的切片。

 func foo(params ...int) { fmt.Println(len(params)) } func main() { foo() foo(1) foo(1,2,3) } 

对于任意可能大量的可选参数,一个很好的习惯用法是使用Functional选项

对于你的Foobartypes,首先只写一个构造函数:

 func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){ fb := &Foobar{} // ... (write initializations with default values)... for _, op := range options{ err := op(fb) if err != nil { return nil, err } } return fb, nil } 

其中每个选项都是使Foobar变异的函数。 然后为您的用户提供使用或创build标准选项的便捷方式,例如:

 func OptionReadonlyFlag(fb *Foobar) error { fb.mutable = false return nil } func OptionTemperature(t Celsius) func(*Foobar) error { return func(fb *Foobar) error { fb.temperature = t return nil } } 

操场

为了简洁起见,您可以给出选项types的名称( Playground ):

 type OptionFoobar func(*Foobar) error 

如果您需要强制参数,请将其作为构造函数的第一个参数添加到可变参数之前。

function选项习惯用法的主要好处是:

  • 随着时间的推移,您的API可以不断增长而不会破坏现有的代码,因为当需要新的选项时,构造器签名保持不变。
  • 它使默认用例成为最简单:完全没有参数!
  • 它提供了对复杂值初始化的精确控制。

这个技巧是由Rob Pike创造的,也是由Dave Cheney演示的,但我找不到确切的链接。 这里是我学习dotGo 2014的演讲 。

Go中不支持可选参数和函数重载。 Go支持可变数量的参数:将parameter passing给…参数

不 – 不是。 根据Go for C ++程序员文档,

Go不支持函数重载,不支持用户定义的操作符。

我无法find一个同样清晰的声明,即可选参数不受支持,但它们也不受支持。

你可以把它很好地封装在一个类似于下面的函数中。

 package main import ( "bufio" "fmt" "os" ) func main() { fmt.Println(prompt()) } func prompt(params ...string) string { prompt := ": " if len(params) > 0 { prompt = params[0] } reader := bufio.NewReader(os.Stdin) fmt.Print(prompt) text, _ := reader.ReadString('\n') return text } 

在这个例子中,默认的提示符在前面有一个冒号和一个空格。 。 。

 : 

。 。 。 但是,您可以通过向提示函数提供参数来覆盖该参数。

 prompt("Input here -> ") 

这将导致如下的提示。

 Input here -> 

我最终使用了params和variadic args结构的组合。 这样,我不必更改多个服务使用的现有接口,并且我的服务能够根据需要传递额外的参数。 golang操场中的示例代码: https : //play.golang.org/p/G668FA97Nu

我有点晚了,但如果你喜欢stream畅的界面,你可以devise你的连线调用像这样:

 type myType struct { s string a, b int } func New(s string, err *error) *myType { if s == "" { *err = errors.New( "Mandatory argument `s` must not be empty!") } return &myType{s: s} } func (this *myType) setA (a int, err *error) *myType { if *err == nil { if a == 42 { *err = errors.New("42 is not the answer!") } else { this.a = a } } return this } func (this *myType) setB (b int, _ *error) *myType { this.b = b return this } 

然后像这样调用它:

 func main() { var err error = nil instance := New("hello", &err). setA(1, &err). setB(2, &err) if err != nil { fmt.Println("Failed: ", err) } else { fmt.Println(instance) } } 

这与@Ripounet的答案中的function选项习语类似,享有相同的好处,但有一些缺点:

  1. 如果发生错误,它不会立即中止,因此,如果您期望您的构造函数经常报告错误,那么效率会稍差。
  2. 你将不得不花费一条线来声明一个errvariables并将其归零。

但是,有一个可能的小优点,这种types的函数调用应该更容易编译器内联,但我真的不是一个专家。