Golang 替代带有默认参数的 C++ 函数:多个函数或结构参数

Sco*_*s S 2 c++ idioms go function-parameter

我想知道 Go 中的最佳实践相当于使用默认参数绑定的 C++ 函数,这对于用户来说可能是最容易看到函数参数的(在 linter 帮助下)。
您认为最 GO 风格、最简单的测试功能使用方式是什么?

C++ 中的示例函数:

void test(int x, int y=0, color=Color());
Run Code Online (Sandbox Code Playgroud)

Go 中的等价

1. 多重签名:

func test(x int)
func testWithY(x int, y int)
func testWithColor(x int, color Color)
func testWithYColor(x int, y int, color Color)
Run Code Online (Sandbox Code Playgroud)

亲:

  • linter 将显示测试的所有可能性
  • 编译器会选择最短路径

缺点:

  • 当参数很多时可能会不知所措

2. 带结构体参数:

type testOptions struct {
    X      int
    Y      int
    color  Color
}

func test(opt *testOptions)

// user 
test(&testOptions{x: 5})
Run Code Online (Sandbox Code Playgroud)

亲:

  • 只有一个签名
  • 只能指定一些值

缺点:

  • 需要定义一个结构体
  • 这些值将由系统默认设置

在模块github.com/cresty/defaults的帮助下,有一种方法可以设置默认值(但需要在运行时调用 Reflect 的成本)。

type testOptions struct {
    X      int
    Y      int `default:"10"`
    color  Color `default:"{}"`
}

func test(opt *testOptions) *hg.Node {
    if err := defaults.Set(opt); err != nil {
        panic(err)
    }
}
Run Code Online (Sandbox Code Playgroud)

亲:

  • 设置默认值

缺点:

  • 在运行时使用reflect

...PS:我看到了可变参数or/with的使用interface{},但我发现很难知道要使用哪些参数(或者也许有一种方法可以向 linter 指示参数列表)。

rus*_*tyx 5

无论哪种方式都可以正常工作,但在 Go 中,功能选项模式可能更适合实现此类功能。

它基于接受可变数量的WithXXX类型的函数参数的思想,这些函数参数扩展或修改调用的行为。

type Test struct {
    X     int
    Y     int
    color Color
}

type TestOption func(*Test)

func test(x int, opts ...TestOption) {
    p := &Test{
        X: x,
        Y: 12,
        Color: defaultColor,
    }
    for _, opt := range opts {
        opt(p)
    }
    p.runTest()
}

func main() {
    test(12)
    test(12, WithY(34))
    test(12, WithY(34), WithColor(Color{1, 2, 3}))
}

func WithY(y int) TestOption {
    return func(p *Test) {
        p.Y = y
    }
}

func WithColor(c Color) TestOption {
    return func(p *Test) {
        p.color = c
    }
}
Run Code Online (Sandbox Code Playgroud)