Golang中*T类型能否拥有T的方法?
Golang中*T类型能否拥有T的方法?
方法 World 属于 *X,但我可以在一个 X 实例上调用它,这是设计如此吗?那么 T 和 *T 的方法集之间是什么关系?它们完全相同吗?非常感谢。
type X struct {}
func (x X) Hello() {
}
func (x *X) World() {
}
func main() {
a := X{}
a.World()
}
哦,我明白你的意思了。我搞混了!看起来Dean的回答解决了你的问题!
更多关于Golang中*T类型能否拥有T的方法?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
谢谢。明白了:通过这种设计,我们有两种方法:按值和按引用。很好!
是的,这是有意为之的设计;以下是语言规范中的相关说明:The Go Programming Language Specification - go.dev。
skillian:
看起来这段话的意思是:*T 的方法集包含了 T 的方法集。但在我的例子中,我在一个 X 实例上调用了 *X 的方法。这应该会失败:World 不是 X 的方法。
简而言之,编译器会自动将 a.World() 转换为 (&a).World()。根据规范中 Calls 部分稍后的说明:
如果
x的(类型的)方法集包含m,并且参数列表可以赋值给m的参数列表,则方法调用x.m()是有效的。如果x是可寻址的并且&x的方法集包含m,那么x.m()是(&x).m()的简写:
StackOverflow上的这个问题有一个很好的观点,指出了两者之间的细微差别以及你可能选择其中一个的原因:
以指针作为接收器的方法能够修改该接收器的值,而以值作为接收器的方法则不能。
该问题中包含大量有用的信息。在处理使用反射的东西时,例如MarshalJSON,我也要小心。在这种情况下,你使用哪种接收器确实很重要。
在Go语言中,*T类型的方法集包含T的方法集,但反过来不成立。这是Go语言设计中的隐式解引用特性。
具体来说:
T类型的方法集包含所有接收者为T的方法*T类型的方法集包含所有接收者为T和*T的方法
在你的代码中,World()方法的接收者是*X,但可以在X实例上调用,这是因为Go编译器会自动进行地址获取和隐式解引用。
示例代码:
package main
import "fmt"
type X struct {
value int
}
// 方法属于 T
func (x X) Hello() {
fmt.Println("Hello from", x.value)
}
// 方法属于 *T
func (x *X) World() {
fmt.Println("World from", x.value)
}
// 另一个示例,展示方法集差异
type Y struct {
data string
}
// 只有 *Y 有这个方法
func (y *Y) Modify() {
y.data = "modified"
}
func main() {
// 示例1:X类型
a := X{value: 1}
// 可以调用,编译器自动转换为 (&a).Hello()
a.Hello()
// 可以调用,编译器自动转换为 (&a).World()
a.World()
// 示例2:Y类型
b := Y{data: "original"}
// 这行会编译错误,因为Modify()只属于*Y
// b.Modify() // 取消注释会报错
// 正确调用方式
(&b).Modify()
fmt.Println(b.data) // 输出: modified
// 或者使用指针变量
c := &Y{data: "pointer"}
c.Modify()
fmt.Println(c.data) // 输出: modified
}
方法集关系总结:
T的方法集:所有接收者为T的方法*T的方法集:所有接收者为T和*T的方法
这种设计允许在需要修改接收者时使用指针接收者,同时在值类型上也能调用这些方法,提高了代码的灵活性。

