Go 语言这种结构体调用方法的写法是怎么回事?

2020-10-05 10:13:33 +08:00
 hakono

无意间发现的一个写法

type T struct {
	t int
}

func (t T) NewT(tValue int) T {
	return T{t: tValue}

}
func main() {
	t := T.NewT(T{},999)
	fmt.Println(t)
}


输出 {999}

没有结构体实例,但是却可以直接调用类型来调用对应的方法

t := T.NewT(T{},999)

这写法有点像调用静态方法

通过一些测试可以知道第一个参数的 T{} 必须存在,传入的第一个参数会被当成方法的 reciver 传入方法中(莫非 go 语言是通过这种机制实现的方法调用) 如果方法不去管传入的 reciver 的话,这种写法似乎可以实现类似调用静态方法的写法?

翻了下似乎没找到这种写法的说明,不知道官网有没有对应的地方介绍(也可能是我没找对地方)

3291 次点击
所在节点    Go 编程语言
8 条回复
cmdOptionKana
2020-10-05 10:29:16 +08:00
https://golang.org/ref/spec

That function may be called normally with an explicit receiver, so these five invocations are equivalent:
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
SingeeKing
2020-10-05 10:30:44 +08:00
Python 和 rust 都是这样
reus
2020-10-05 11:41:13 +08:00
方法本来就是一个函数,这个函数的第一个参数就是 receiver,所以可以用这个方式调用
littlewing
2020-10-05 11:52:55 +08:00
t := T.NewT(T{},999)
等价于
t := T{}.NewT(999)
user8341
2020-10-06 07:14:07 +08:00
虽然能跑,但是这种写法不太正规。
t := T.NewT(T{},999)
这句的 T{}创建了一个新对象,以传值方式传给 NewT 函数。然后 NewT 函数完全没用到传进来的这个对象,
而是在 return 的时候又创建了一个新的对象 T{t: tValue},
然后回到 main()函数,它又以复制的方式赋给 t 变量(这又是另一个对象)
reus
2020-10-06 08:50:03 +08:00
@user8341 如果 receiver 是 T,那调用的时候,就是复制再传参的。所有参数都是复制再传递的。不要以为用对象调用方法,就不会复制。T 和*T 两种 receiver 是有区别的
sunriz
2020-10-06 11:45:26 +08:00
调用 type.method 实际上就是把 method 的 receiver 暴露为参数了
一般就这两种:
1. type.method(type{},...)
2. (*type).method(new(type),...)
看 method 怎么的定义了
user8341
2020-10-06 13:57:41 +08:00
@reus 我的答案你没看懂。不过谢谢您的补充。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/712577

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX