go的方法值和方法表达式

go的方法可分为方法值(method value),和方法表达式(method expression) 2种情况

准备工作

定义一个结构体,并且声明接收者方法

type User struct {
   id   int
   name string
}

func (self User) Test() {
   fmt.Printf("%p,%v\n", self, self)
}



方法值

直接将方法声明赋值给新变量:

func main() {
   u := User{1, "tioncico"}
   u.Test()
   fun1 := u.Test
   u.name="tioncico2"
   fun1()
   u.Test()
}

输出:

GOROOT=/Users/tioncico/sdk/go1.17 #gosetup
GOPATH=/Users/tioncico/go/pkg/mod #gosetup
/Users/tioncico/sdk/go1.17/bin/go build -o /private/var/folders/08/hkdkrdpn4mbb_4l5zbvrq0hh0000gp/T/___go_build_main_go /Users/tioncico/GolandProjects/LearnGoProject/main.go #gosetup
/private/var/folders/08/hkdkrdpn4mbb_4l5zbvrq0hh0000gp/T/___go_build_main_go
%!p(main.User={1 tioncico}),{1 tioncico}
%!p(main.User={1 tioncico}),{1 tioncico}
%!p(main.User={1 tioncico2}),{1 tioncico2}

可看出,方法值为值传递方式,更改name后,fun1的数值并没有更改



方法表达式

func main() {
   u := User{1, "tioncico"}
   u.Test()
   fun1 := (User).Test
   u.name="tioncico2"
   fun1(u)
   u.Test()
}

输出:

GOROOT=/Users/tioncico/sdk/go1.17 #gosetup
GOPATH=/Users/tioncico/go/pkg/mod #gosetup
/Users/tioncico/sdk/go1.17/bin/go build -o /private/var/folders/08/hkdkrdpn4mbb_4l5zbvrq0hh0000gp/T/___go_build_main_go /Users/tioncico/GolandProjects/LearnGoProject/main.go #gosetup
/private/var/folders/08/hkdkrdpn4mbb_4l5zbvrq0hh0000gp/T/___go_build_main_go
%!p(main.User={1 tioncico}),{1 tioncico}
%!p(main.User={1 tioncico2}),{1 tioncico2}
%!p(main.User={1 tioncico2}),{1 tioncico2}


其实可以看出,方法值为 "具体实例的方法",已经存在具体实例,需要通过实例去调用接收者方法,所以不需要额外传入接收者

 而方法表达式为:"结构体的方法",需要额外传入结构体进行实际调用



其他

package main

import "fmt"

type User struct {
   id   int
   name string
}

func (self *User) Test() {
   fmt.Printf("%p,%v\n", self, self)
}

func main() {
   var u *User=nil
   u.Test()  //直接实例调用
   (*User)(nil).Test()  //方法值实例(实例值为nil)调用
   (*User).Test(nil)  //方法表达式,传入实例(实例为nil)调用
}



仙士可博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论
  • 本站由白俊遥博客程序搭建
    © 2017-1-17 php20.cn 版权所有 ICP证:闽ICP备17001387号
  • 本网站由: 提供cdn加速/云存储服务
  • 联系邮箱:1067197739@qq.com