分享
  1. 首页
  2. 文章

goLang 之 type Method Value 和Method Expressions

soledad · · 1310 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

在使用goLang时,经常遇到Method ValueMethod Expressions的问题,简单记录一下两者的使用区别

goLangtype类型方法定义如下:

 func (p myType) funcName(q type) (r,s type){return 0,0) //类似这样

本质上这就是一种语法糖,方法调用如下:


instance.method(args) ---> (type).func(instance,args)

instance就是Receiver. 左边的称为Method value.右边的则是Method Expression.其实goLang 是推荐使用左边形式的,因为比较好理解。Method Value是包装后的状态对象,总是与特定的对象实例关联在一起,而Method Expression函数将Receiver作为第一个显示参数,调用时需手动传递。二者本质没有什么区别

只是Method value看起来更像面向对象的格式,且编译器会自动进行类型转换。 Method Expression更直观,更底层,编译器不会进行优化,会按照实际表达意义去执行。

Method Value赋值给变量,Receiver实例立即被复制,这个和goLang的一贯作风是一样的。只进行值传递,即使是传递指针,也只是传递指针的拷贝,只是拷贝的指针和原指针都指向一个地方,看起来好像是直接操作原数据

instance.method(args):可以用 value(值)pointer(指针) 变量调用所有绑定的任何方法,编译器会自动进行类型转换,转换后的效果和method的定义语义一致,和调用者的样式没有关系。

method定义的Receivervalue形的,即使使用pointer实例变量调用该方法,也是value值拷贝;

method定义的Receiverpointer形的,即使使用value 实例变量调用该方法,也能改变Receiver实例状态。


package main 
 
import ( 
 "fmt" 
) 
 
 
type Person struct { 
 Age int 
 Name string 
} 
 
 
func (this Person) Getage() int{ 
 return this.Age 
} 
 
func (this *Person) Setage(i int){ 
 this.Age = i 
} 
 
func main(){ 
 //初始化s1,s2 
 s1:= Person{Age:12, Name: "tata"} 
 s2:= &Person{Age:100, Name: "tt"} 
 fmt.Println("s1=",s1) 
 fmt.Println("s2=",s2) 
 fmt.Println("------------------------") 
 
 //可以用 value 或 pointer 调用所有绑定的方法,编译器自动进行类型转换(按照method Reciever 的类型是value还是pointer进行转换,和调用者调用表现形式没有任何关系,调用执行结果按照method的定义语义进行解释) 
 
 fmt.Println("s1.Age=",s1.Getage()) 
 fmt.Println("s2.Age=",s2.Getage()) 
 fmt.Println("s2.Age=",(*s2).Getage()) 
 s1.Setage(110) 
 s2.Setage(101) 
 fmt.Println("s1=",s1) 
 fmt.Println("s1=",s2) 
 (&s1).Setage(220) 
 fmt.Println("s1=",s1) 
 fmt.Println("------------------------") 
 
//如下是Method Value形式引用,其等价于Reciever直接调用,规则和直接调用完全一致 
 f := s1.Getage 
 s1.Setage(330) 
 fmt.Println("s1=",s1) 
 fmt.Println("s1.copy.Getage()=",f()) 
 fmt.Println("s1=",s1) 
 
//如下四种方式也是Method Values模式,编译器进行自动转换,任何形式都可以调用成功 
 fmt.Println("------------------------") 
 sw := (&s1).Setage 
 f2 := (&s1).Getage 
 sw(880) 
 fmt.Println("s1=",s1) 
 fmt.Println("s1.copy.Getage()=",f2()) 
 fmt.Println("s1=",s1) 
 
 ss := s1.Setage 
 f3 := s1.Getage 
 ss(990) 
 fmt.Println("s1=",s1) 
 fmt.Println("s1.copy.Getage()=",f3()) 
 fmt.Println("s1=",s1) 
 
 se := s2.Setage 
 f4 := s2.Getage 
 se(110) 
 fmt.Println("s2=",s2) 
 fmt.Println("s2.copy.Getage()=",f4()) 
 fmt.Println("s2=",s2) 
 
 se2 := (*s2).Setage 
 f5 := (*s2).Getage 
 se2(220) 
 fmt.Println("s2=",s2) 
 fmt.Println("s2.copy.Getage()=",f5()) 
 fmt.Println("s2=",s2) 
 
//如下是Method Expressions, methods Reciever是T,可以被T和*T Type调用; methods Reciever是*T,则只能被*T Type调用;调用第一个参数类型要和调用者一致:T对应T类型变量,*T对用*T类型变量 
// T.Method.(var T) 
// (*T).Method.(var * T) 
 
 fmt.Println("------------------------") 
 m := Person.Getage(s1) 
 //m5 := Person.Getage(&s1) 报错,前后类型不一致 
 //m6 := Person.Getage(s2) 报错,前后类型不一致 
 m2 := (*Person).Getage(&s1) 
 n := (*Person).Getage(s2) 
 n2 := Person.Getage(*s2) 
 fmt.Println("m=",m) 
 fmt.Println("m2=",m2) 
 fmt.Println("n2=",n) 
 fmt.Println("n2=",n2) 
 
 fmt.Println("------------------------") 
 //Person.Setage(s1,9999)不允许, *T类型方法,T不能调用 
 //Person.Setage(&s1,9999)也是不允许,*T类型方法,T不能调用 
 (*Person).Setage(s2,500) 
 fmt.Println("s2=",s2) 
 
 //(*Person).Setage(s1,1000) 不允许 ,前后类型不一致 
 //Person.Setage(s2,1000) 不允许 
 (*Person).Setage(&s1,1000) 
 fmt.Println("s1=",s1) 
 }

其实有过面向对象经验,对于method value会比较容易理解,可以非常灵活使用。而对于method expression,重点理解如下一段话就可以:

methods ReceiverT,可以被T*T Type调用;
methods Receiver*T,则只能被*T Type调用;

调用的时候第一个参数类型要和调用者一致:T对应T类型变量,*T对用*T类型变量

参考:http://blog.csdn.net/hittata/...


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:soledad

查看原文:goLang 之 type Method Value 和Method Expressions

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1310 次点击
2 回复 | 直到 2018年02月09日 17:23:06
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏