2023-06-01 07:00:00

Go?

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


当前回答

Go语言不支持方法重载,但你可以像可选参数一样使用可变参数,也可以使用interface{}作为参数,但这不是一个好的选择。

其他回答

Go语言不支持方法重载,但你可以像可选参数一样使用可变参数,也可以使用interface{}作为参数,但这不是一个好的选择。

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

方法调度被简化了 不需要做类型匹配 好。有使用其他语言的经验 告诉我们有各种各样的 方法,但名称相同 偶尔会有不同的签名 有用,但也可能有用 在实践中令人困惑和脆弱。 仅通过名称和要求进行匹配 类型的一致性是主要因素 简化围棋类型中的决策 系统。

不——都不是。根据Go for c++程序员文档,

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

我找不到一个同样明确的声明,说明可选参数不受支持,但它们也不受支持。

您可以通过映射传递任意命名参数。如果参数具有不一致的类型,则必须使用“aType = map[key].(*foo.type)”断言类型。

type varArgs map[string]interface{}

func myFunc(args varArgs) {

    arg1 := "default"
    if val, ok := args["arg1"]; ok {
        arg1 = val.(string)
    }

    arg2 := 123
    if val, ok := args["arg2"]; ok {
        arg2 = val.(int)
    }

    fmt.Println(arg1, arg2)
}

func Test_test() {
    myFunc(varArgs{"arg1": "value", "arg2": 1234})
}

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

对于你的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
  }
}

操场上

为简洁起见,你可以给选项的类型命名(Playground):

type OptionFoobar func(*Foobar) error

如果需要强制参数,将它们作为构造函数的第一个参数添加到可变参数选项之前。

Functional options成语的主要好处是:

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

这个技巧是由Rob Pike创造的,也由Dave Cheney演示过。