GO语言对方法传值和方法集的理解

go语言中的方法和函数的区别就是方法多了一个传值,例如:

函数:

func notify(){
   fmt.Println("HelloWord")
}

方法:

func (u *user) notify(){
   fmt.Println(u.name)
}

首先要明确两个定义,一个就是方法定义时选择的接收者,也就是(u *user),可以是值接收者,

也可以是指针接收者;另一个定义就是你在使用方法时传入的值是指针还是值。

在通常情况下,go会在执行的时候尽量减少错误,比如:

1、当方法是值接收者,你传的值是指针的时候

type n interface {
   notify()
}

type user struct {
   name string
}

func (u user) notify(){
   fmt.Println(u.name)
}
func main(){
   u := &user{"bill"}
   u.notify()
}

这时能正常执行,因为go在代码执行的背后转为 (*u).notify(),这是go编辑器为了支持这种方法

调用背后做的事情,指针被解引用为值,这样就符合了值接收者的要求,notify操作的是一个副本,

只不过这次操作的是从u指针指向的值的副本。

2、当方法是指针接收者,你传的值是值的时侯(重复代码不再写,如上):

func (u *user) notify(){
   fmt.Println(u.name)
}
func main(){
   u := user{"bill"}
   u.notify()
}

这时能正常执行,因为go在代码执行的背后转为 (&u).notify(),go首先引用u值得到了

一个指针,这个指针再匹配方法的接收者类型进行调用。


以上是一种正常的情况,但是并不是所有的情况go都能进行转化,这是就出现了方法集。

规范描述的方法集:

Values(你传入的值):T(值类型)          MR(方法定义的接收者类型):T(值类型)

Values(你传入的值):*T(指针类型)          MR(方法定义的接收者类型):T(值类型) 和 *T(指针类型)

如果上面看的别扭的话,可以从接收者类型的角度来看:

MR(方法定义的接收者类型):T(值类型)                Values(你传入的值):T(值类型)和 *T(指针类型)

MR(方法定义的接收者类型):*T(指针类型)         Values(你传入的值):*T(指针类型)

也就是说方法定义的时候是值接受者类型,在用的时候就可以传入值类型和指针类型,

如果方法定义的时候是指针类型,在用的时候就只能是指针类型,因为有的情况go并不能获得指针,比如:

1、

type n interface {
   notify()
}

type user struct {
   name string
}

func (u *user) notify(){
   fmt.Println(u.name)
}
func main(){
   u := user{"bill"}
   s(u)    //重点
}
func s(n n){
   n.notify()
}

这段程序在编译器会直接报错,s(u) 这行错误,因为方法定义的是指针接收者,这样传进s函数的就是

一个复制后的值,go不能再找到原来的值的地址,就会报错,可以改为s(&u),就正确了。

2、

type n interface {
   notify()
}

type user struct {
   name string
}

func (u *user) notify(){
   fmt.Println(u.name)
}
func main(){
   user{"qew"}.notify()
}

这段代码中,main函数中,go也找不到地址,也会报错,所以方法集定义的规则在哪种情况下都不会出错,

也就是强调了指针接收者的情况下,传入的值必须是地址。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值