向构造函数添加可变参数时如何在 Go 中进行版本控制?

How to do versioning in Go when adding a variadic parameter to a constructor?

我认为将可变参数函数添加到常规函数或方法会破坏基于 . But what about adding variadic parameters to a constructor function? like adding Functional Options 的更改。

通过使用 semver 此代码为 v1.0.0

type Foo struct{}

// constructor with default behavior
func NewFoo() *Foo {
    return &Foo{}
}

添加可变参数

type Foo struct{}

type Option func(&Foo)

// constructor with option
func NewFoo(opts ...Option) *Foo {
    // process option before return
    // ...
    return &Foo{}
}

旧代码在调用构造函数时仍然很好,没有人将构造函数分配给变量并将构造函数传递给另一个函数,如

那么,在上面的代码中,我应该将主要版本增加到 v2.0.0 还是将次要版本增加到 v1.1.0?

我认为两者都可以,因为这是一个灰色地带。原则上你破坏了向后兼容性,因为函数的签名发生了变化,但实际上调用者不太可能受到影响。

这相当于将字段添加到结构中,该结构对新字段具有合理的默认零值解释。使用这些结构的代码可能会有不同的行为(例如,如果它们查看结构的大小,或者如果它们使用反射),但将此称为重大更改是不务实的,除非您期望人们正在做这些边缘情况东西。

In Go, should I increment the major version to v2.0.0 or the minor one to v1.1.0?


在 Go 中,NewFoo 函数类型

v1.0.0:

type Foo struct{}

func NewFoo() *Foo {}

v2.0.0:

type Foo struct{}

type Option func(*Foo)

func NewFoo(opts ...Option) *Foo { }

是不同的类型。这使它成为一个重大变化,对主要版本号的更新。


然而,这并不是真正的重大变化,只是一个扩展,所以更新次要版本号。使用相似但不同的函数名称。例如,NewFooNewFooOpts.

v1.1.0:

type Foo struct{}

func NewFoo() *Foo {
    return NewFooOpts()
}

type Option func(*Foo)

func NewFooOpts(opts ...Option) *Foo {
    var foo Foo
    for _, opt := range opts {
        // handle opt
        _ = opt
    }
    return &foo
}

游乐场:https://play.golang.org/p/HcN1WCi0YK4

使用记录功能的注释来指导用户使用哪个功能。例如,函数 NewFoo 可能已被弃用,取而代之的是函数 NewFooOpts.


No one assigns constructor to a variable and passing around constructor to another function.


因为有人这样做,所以这个说法是错误的。