📗【Go 原理】结构体方法:值接收者与指针接收者的区别 #73
Replies: 8 comments
-
最后一段代码可以编译通过呀 |
Beta Was this translation helpful? Give feedback.
-
这篇文章其实是想说将结构体作为接口类型、去调用接口的方法时,会出现的问题。这篇文章我代码写错了,谢谢你指出来。我更新了下能编译通过和不能编译通过的版本,可以看看。 |
Beta Was this translation helpful? Give feedback.
-
最后一段代码 |
Beta Was this translation helpful? Give feedback.
-
@dgqypl 有道理。这里用 bar 是为了说明下就算参数里是指针,实际上改的也是某个局部变量结构体,这样就和指针的思路矛盾了,所以不允许这种编译方法。 |
Beta Was this translation helpful? Give feedback.
-
在我看到过的资料中是以这个角度进行说明的:
因此,这段代码之所以能够编译通过: type Inter interface {
foo()
}
type S struct{}
func (s S) foo() {}
var a Inter = &S{}
a.foo() 是由于a是S的指针类型,其方法集合自动包括了S的所有方法,所以能够编译通过。 而下面这段代码之所以不能编译通过: type Inter interface {
foo()
}
type S struct{}
func (s *S) foo() {
}
var a Inter = S{}
a.foo() 是由于a的类型是S,其方法集合不包括其指针类型的方法,而实现接口Inter的是其指针类型,所以不能编译通过。 供参考。 |
Beta Was this translation helpful? Give feedback.
-
@dgqypl 这个很详细啊,学习了。感谢分享。 之前做这个笔记的时候只是参考了下 draveness 的博客,没有自己研究,问题有点多。 |
Beta Was this translation helpful? Give feedback.
-
其实你的文章讲述了一个很重要的概念,对很多同学很有帮助(包括我),即Go语言中结构体是值类型,指针是引用类型,因此在进行类似的赋值时: var a = S{bar: 100}
b := a // 由于a是结构体(值类型),b是对a的一个完全拷贝,修改b并不会影响a
var a = &S{bar: 100}
b := a // a是结构体的指针(引用类型),b与a对应同一个底层的结构体,修改b会影响a 所以代码的运行结果: type Inter interface {
foo()
}
type S struct {
bar int
}
func (s *S) foo(i int) {
s.bar = i
}
func main() {
var a = S{bar: 100}
b := a
b.foo(1)
fmt.Println(a.bar) // 100
} type Inter interface {
foo()
}
type S struct {
bar int
}
func (s *S) foo(i int) {
s.bar = i
}
func main() {
var a = &S{bar: 100}
b := a
b.foo(1)
fmt.Println(a.bar) // 1
} 就如你文中所述的一样。 另,关于
也可以参见Go的官方FAQ |
Beta Was this translation helpful? Give feedback.
-
文章的这个角度切入点非常好,基本上能够理解您要表达的核心观点:即当使用值类型结构体调用接收者为指针类型的方法时,即使可以成功通过编译,那么修改的是也是另一个副本的值,不会影响到原结构体,与传递指针修改值的初衷不符,因此 go 的编译器不会让这种情况通过编译。 我还曾接触过另外一种说法:一个结构体只要实现了值接收者方法,那么将自动实现指针接收者方法,反之则不成立。如果一个结构体实现了指针接收者方法,同时自动实现对应的值接收者方法,那么原本期望对原结构体的修改就无法实现,因为值类型方法只会产生一个副本调用者去调用该方法,不会影响到原调用者。 |
Beta Was this translation helpful? Give feedback.
-
https://imageslr.github.io/2019/11/12/go-underlying-struct-method.html
方法的接收者类型可以是:值、指针,结构体变量的类型可以是:值、指针。这样能够组合出四种不同情况,只有一种会发生编译不通过的问题,即结构体类型为值类型、调用接收者为指针的方法。但是反过来,结构体为指针类型时,却可以调用接收值为值或指针的任何方法。这是为什么呢?
Beta Was this translation helpful? Give feedback.
All reactions