向构造函数添加可变参数时如何在 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 { }
是不同的类型。这使它成为一个重大变化,对主要版本号的更新。
然而,这并不是真正的重大变化,只是一个扩展,所以更新次要版本号。使用相似但不同的函数名称。例如,NewFoo
和 NewFooOpts
.
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.
因为有人这样做,所以这个说法是错误的。
我认为将可变参数函数添加到常规函数或方法会破坏基于
通过使用 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 { }
是不同的类型。这使它成为一个重大变化,对主要版本号的更新。
然而,这并不是真正的重大变化,只是一个扩展,所以更新次要版本号。使用相似但不同的函数名称。例如,NewFoo
和 NewFooOpts
.
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.
因为有人这样做,所以这个说法是错误的。