分享
go方法的深入探究(7.21增补)
刘地 · · 3132 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
1)哪些类型可以有方法:
1)只能对命名类型和命名类型的指针编写方法;
2)不能对接口类型和接口类型的指针编写方法;
3)只能在定义命名类型的那个包编写其方法。
2)receiver是值的方法,编译器会隐式的生成一个receiver是对应类型指针的同名方法。反过来却不会。
3)结构体的匿名字段的类型限制:
1)不可以是未命名类型;
2)可以是命名类型或命令类型的指针类型;
3)接口类型可以,接口类型的指针类型不行;
4)结构体匿名字段的方法向外传递的规则:
1)匿名字段为值类型时:值的方法会传递给结构体的值,指针的方法会传递给结构体的指针;
2)匿名字段为指针类型时:指针的方法会传递给值和指针;
3)匿名字段为接口类型时:方法会传递给值和指针;
5)匿名字段的方法,是被经过包装实现为外围结构体的方法。
6)使用具体的类型去调用方法时。
首先,编译器查看该类型下有没有该方法;
其次,扩展查看该类型的指针类型或者基类型(如果该类型是指针类型);
最后,如果以上查找都未找到,则会报错。
注:扩展查看不会查看隐式实现的方法(匿名字段传递出来的方法、值=>指针隐式实现的方法)
7)具体类型的方法集是以该类型为receiver的方法的集合。
8)接口类型的方法集就是其定义里声明的方法,接口调用方法时类似C++调用虚函数;接口的指针没有方法集。
9)类型存入接口时只检查方法集;调用接口的方法时也只检查方法集;reflect包同样只查看方法集。
因此:
类型A的方法,A和*A都可以调用;
类型A的方法,虽然隐式实现了类型*A的方法,**A却不能调用;
类型*A的方法,A、*A、**A都可以调用;
不能实现**A的方法;
1)只能对命名类型和命名类型的指针编写方法;
2)不能对接口类型和接口类型的指针编写方法;
3)只能在定义命名类型的那个包编写其方法。
2)receiver是值的方法,编译器会隐式的生成一个receiver是对应类型指针的同名方法。反过来却不会。
3)结构体的匿名字段的类型限制:
1)不可以是未命名类型;
2)可以是命名类型或命令类型的指针类型;
3)接口类型可以,接口类型的指针类型不行;
4)结构体匿名字段的方法向外传递的规则:
1)匿名字段为值类型时:值的方法会传递给结构体的值,指针的方法会传递给结构体的指针;
2)匿名字段为指针类型时:指针的方法会传递给值和指针;
3)匿名字段为接口类型时:方法会传递给值和指针;
5)匿名字段的方法,是被经过包装实现为外围结构体的方法。
6)使用具体的类型去调用方法时。
首先,编译器查看该类型下有没有该方法;
其次,扩展查看该类型的指针类型或者基类型(如果该类型是指针类型);
最后,如果以上查找都未找到,则会报错。
注:扩展查看不会查看隐式实现的方法(匿名字段传递出来的方法、值=>指针隐式实现的方法)
7)具体类型的方法集是以该类型为receiver的方法的集合。
8)接口类型的方法集就是其定义里声明的方法,接口调用方法时类似C++调用虚函数;接口的指针没有方法集。
9)类型存入接口时只检查方法集;调用接口的方法时也只检查方法集;reflect包同样只查看方法集。
类型A的方法,A和*A都可以调用;
类型A的方法,虽然隐式实现了类型*A的方法,**A却不能调用;
类型*A的方法,A、*A、**A都可以调用;
不能实现**A的方法;
type A ...
func (a A)X(){}
func (a *A)Y(){}
type IX interface{
X()
}
type IY interface{
Y()
}
a := A{}
b := &a
c := &b
a.X() // ok
b.X() // ok
c.X() // error
a.Y() // ok
b.Y() // ok
c.Y() // ok
var ix IX
ix = a // ok
ix = b // ok
ix = c // error
var iy IY
iy = a // error
iy = b // ok
iy = c // error
var jx IX
jx = ix // ok
jx = &ix // error
对于代码:
type I interface {
IE()
}
type A int
func (_ A) VA() {}
func (_ *A) PA() {}
type B struct {
I
}
func (_ B) VB() {}
func (_ *B) PB() {}
type C struct {
A
}
func (_ C) VC() {}
func (_ *C) PC() {}
type D struct {
*A
}
func (_ D) VD() {}
func (_ *D) PD() {}
下面的列表说明了其方法集和方法的来源:
type(类型)
explicit(显式定义的方法)
implicit(隐式实现的方法)
inherit(继承自匿名字段的方法)
implicit(隐式实现的方法)
inherit(继承自匿名字段的方法)
I
IE
*I
A
VA
*A
PA
VA
B
VB
IE
IE
*B
PB
VB
IE
C
VC
VA
VA
*C
PC
VC
PA,VA
D
VD
PA,VA
PA,VA
*D
PD
VD
PA,VA
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信3132 次点击
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
1)只能对命名类型和命名类型的指针编写方法;
2)不能对接口类型和接口类型的指针编写方法;
3)只能在定义命名类型的那个包编写其方法。
2)receiver是值的方法,编译器会隐式的生成一个receiver是对应类型指针的同名方法。反过来却不会。
3)结构体的匿名字段的类型限制:
1)不可以是未命名类型;
2)可以是命名类型或命令类型的指针类型;
3)接口类型可以,接口类型的指针类型不行;
4)结构体匿名字段的方法向外传递的规则:
1)匿名字段为值类型时:值的方法会传递给结构体的值,指针的方法会传递给结构体的指针;
2)匿名字段为指针类型时:指针的方法会传递给值和指针;
3)匿名字段为接口类型时:方法会传递给值和指针;
5)匿名字段的方法,是被经过包装实现为外围结构体的方法。
6)使用具体的类型去调用方法时。
首先,编译器查看该类型下有没有该方法;
其次,扩展查看该类型的指针类型或者基类型(如果该类型是指针类型);
最后,如果以上查找都未找到,则会报错。
注:扩展查看不会查看隐式实现的方法(匿名字段传递出来的方法、值=>指针隐式实现的方法)
7)具体类型的方法集是以该类型为receiver的方法的集合。
8)接口类型的方法集就是其定义里声明的方法,接口调用方法时类似C++调用虚函数;接口的指针没有方法集。
9)类型存入接口时只检查方法集;调用接口的方法时也只检查方法集;reflect包同样只查看方法集。
类型A的方法,A和*A都可以调用;
类型A的方法,虽然隐式实现了类型*A的方法,**A却不能调用;
类型*A的方法,A、*A、**A都可以调用;
不能实现**A的方法;
type A ...
func (a A)X(){}
func (a *A)Y(){}
type IX interface{
X()
}
type IY interface{
Y()
}
a := A{}
b := &a
c := &b
a.X() // ok
b.X() // ok
c.X() // error
a.Y() // ok
b.Y() // ok
c.Y() // ok
var ix IX
ix = a // ok
ix = b // ok
ix = c // error
var iy IY
iy = a // error
iy = b // ok
iy = c // error
var jx IX
jx = ix // ok
jx = &ix // error
对于代码:
type I interface {
IE()
}
type A int
func (_ A) VA() {}
func (_ *A) PA() {}
type B struct {
I
}
func (_ B) VB() {}
func (_ *B) PB() {}
type C struct {
A
}
func (_ C) VC() {}
func (_ *C) PC() {}
type D struct {
*A
}
func (_ D) VD() {}
func (_ *D) PD() {}
下面的列表说明了其方法集和方法的来源:
type(类型)
explicit(显式定义的方法)
implicit(隐式实现的方法)
inherit(继承自匿名字段的方法)
implicit(隐式实现的方法)
inherit(继承自匿名字段的方法)
I
IE
*I
A
VA
*A
PA
VA
B
VB
IE
IE
*B
PB
VB
IE
C
VC
VA
VA
*C
PC
VC
PA,VA
D
VD
PA,VA
PA,VA
*D
PD
VD
PA,VA