英文:
In go, is it backwards compatible to change a receiver struct from a value to a pointer?
问题
从代码开始:
type Foo struct {
V bool
}
func (f Foo) bar() bool {
return f.V
}
在不增加主版本号的情况下,可以将其更改为 func (f *Foo) bar() bool
吗?也就是说,假设您知道类型没有线程安全问题。如果是这样,反向更改也是允许的,对吗?
根据我所知,无论变量是值还是指针,调用该函数的任何代码在进行这两个更改后都将继续编译并按预期工作。
英文:
Starting with code like:
type Foo struct {
V bool
}
func (f Foo) bar() bool {
return f.V
}
Is it allowed to change to func (f *Foo) bar() bool
without incrementing the major version number? That is, assuming you know there are no thread safety issues with your type. If so, the reverse change is allowed too, correct?
Any code that called the function regardless of whether the variable was a value or a pointer would continue to compile and work as expected after both changes, as far as I can tell.
答案1
得分: 1
如果对于类型 Foo
,你有一个使用值接收器的方法:
func (f Foo) Method() {...}
那么这个方法对于 Foo
和 *Foo
都是定义的,并且对于这两种情况,该方法接收的是 Foo
实例的副本。如果你将其改为:
func (f *Foo) Method() {...}
那么 Foo.Method
只能在 *Foo
上使用,而不能在 Foo
上使用。因此,这样的改变可能会导致编译错误。
如果你有一个使用指针接收器声明的方法,现在将其改为值接收器,那么你声明的方法将适用于 Foo
和 *Foo
,所以你不应该有编译错误。方法的语义也会发生变化,因为现在即使该实例是可寻址的或者是指针,Method
也会接收 Foo
实例的副本。
英文:
If for a type Foo
you have a method with value receiver:
func (f Foo) Method() {...}
Then this method is defined for both Foo
and *Foo
, and for both cases, the method receives a copy of the instance of Foo
. If you change this to :
func (f *Foo) Method() {...}
then Foo.Method
is only available for *Foo
, and not for Foo
. Thus, such a change may cause compile errors.
If you have a method declared with pointer receiver and now you change that to a value receiver, you declare the method for both Foo
and *Foo
, so you should not have compile errors. The semantics of the method will also change, because now Method
will receive a copy of the instance of Foo
even if that instance is addressable, or it is a pointer.
答案2
得分: 1
根据评论,这个答案提供了关于T
和*T
接收器类型的很好的总结。以下是一些例子,其中从func (f Foo) bar() bool
更改为func (f *Foo) bar() bool
会破坏现有代码。
例子1:T
不可寻址(playground):
type Foo struct {
V bool
}
func (f *Foo) bar() bool { // 将其改为 `(f Foo)`,这样就能正常工作
return f.V
}
func x() Foo {
return Foo{true}
}
func main() {
fmt.Printf("%v", x().bar())
}
例子2:接口(playground):
type Foo struct {
V bool
}
func (f *Foo) bar() bool { // 将其改为 `(f Foo)`,这样就能正常工作
return f.V
}
type Fooer interface {
bar() bool
}
func main() {
var x Fooer
x = Foo{}
fmt.Println(x.bar())
}
英文:
As per the comments, this answer answer provides a good summary T
vs *T
receiver types. Following are a couple of examples where a change from func (f Foo) bar() bool
to func (f *Foo) bar() bool
would break existing code.
Example 1: T
is not addressable (playground):
type Foo struct {
V bool
}
func (f *Foo) bar() bool { // Change to `(f Foo)` and this will work
return f.V
}
func x() Foo {
return Foo{true}
}
func main() {
fmt.Printf("%v", x().bar())
}
Example 2: Interface (playground):
type Foo struct {
V bool
}
func (f *Foo) bar() bool { // Change to `(f Foo)` and this will work
return f.V
}
type Fooer interface {
bar() bool
}
func main() {
var x Fooer
x = Foo{}
fmt.Println(x.bar())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论