题
可以去有可选择的参数?或者我可以界定两个职能相同的名称和不同数量的参数数?
解决方案
Go没有可选参数也不支持方法重载:
如果它方法调度被简化 并不需要做类型匹配的 好。与其他语言的经验 告诉我们,具有各种 具有相同名称的方法,但 不同的签名是偶然 有用的,但它也可能是 混乱和在实践中脆弱。 只有名称和需要匹配 在类型的一致性是一个重大的 在围棋的类型决定简化 系统
其他提示
一个很好的方法,以实现类似的可选参数是使用可变参数ARGS。该功能实际上接收指定任何类型的切片。
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}
可以使用结构,其中包括的参数:
type Params struct {
a, b, c int
}
func doIt(p Params) int {
return p.a + p.b + p.c
}
// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})
对于任意的、潜在的大量可选择的参数,一个很好的惯用语是使用 功能的选择.
你的类型 Foobar
, 首先请只有一个构造:
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.然后提供便利的方式为用户使用,或者创建的标准选项,例如:
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
}
}
为简明起见,你可以给一个名称的类型选项(游乐场) :
type OptionFoobar func(*Foobar) error
如果你需要的强制性参数,把它们添加为第一个参数的构造之前可变 options
.
主要好处的 功能的选择 谚语是:
- 你API可以随着时间的推移而不破坏现有的编码,因为constuctor签名住宿的同时,新的选项是必要的。
- 它使得能够默认使用的情况下将其最简单的:没有参数。
- 它提供了很好的控制的初始化的复杂值。
无论可选参数也不函数重载在Go被支持。围棋不支持可变数量的参数:传递参数...参数
没有 - 既不。每href="http://golang.org/doc/go_for_cpp_programmers.html#top" rel="nofollow noreferrer">去为C ++程序员文档的
Go不支持功能
超载和不支持用户
定义的操作符。 我无法找到一个同样清晰的声明可选参数不受支持,但他们也不支持。
您可以用类似于下面的是一个FUNC很好地封装了这一点。
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和可变参数ARGS的结构的组合。这样一来,我没有改变被多个服务所消耗现有的接口和我的服务能够根据需要通过额外的PARAMS。在golang操场示例代码: https://play.golang.org/p/G668FA97Nu
我是有点晚了,但如果你喜欢流畅的界面,你可以设计自己的setter方法是这样链式调用:
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答案,并享有相同的好处,但也有一些缺点:
- 如果发生错误,它不会立即中止,因此,它将如果你希望你的构造函数经常报告错误稍微低效率的。
- 您将不得不花费行声明一个变量
err
和归零了。
醇>
有,然而,可能小的优势,这种类型的函数调用应该是更容易为编译器内联,但我真的不是个专家。
转至语言不支持方法重载,但你可以使用可变参数ARGS就像可选参数,也可以使用接口{}作为参数,但它不是一个很好的选择。
可以传递任意命名参数与地图。
type varArgs map[string]interface{}
func myFunc(args varArgs) {
arg1 := "default" // optional default value
if val, ok := args["arg1"]; ok {
// value override or other action
arg1 = val.(string) // runtime panic if wrong type
}
arg2 := 123 // optional default value
if val, ok := args["arg2"]; ok {
// value override or other action
arg2 = val.(int) // runtime panic if wrong type
}
fmt.Println(arg1, arg2)
}
func Test_test() {
myFunc(varArgs{"arg1": "value", "arg2": 1234})
}