在Go语言中,将接收者结构体从值类型更改为指针类型是否向后兼容?

huangapple go评论85阅读模式
英文:

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())
}

huangapple
  • 本文由 发表于 2023年7月21日 10:39:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76734799.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定