go的方法可分为方法值(method value),和方法表达式(method expression) 2种情况
准备工作
定义一个结构体,并且声明接收者方法
代码语言:javascript复制type User struct {
id int
name string
}
func (self User) Test() {
fmt.Printf("%p,%vn", self, self)
}
方法值
直接将方法声明赋值给新变量:
代码语言:javascript复制func main() {
u := User{1, "tioncico"}
u.Test()
fun1 := u.Test
u.name="tioncico2"
fun1()
u.Test()
}
输出:
代码语言:javascript复制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的数值并没有更改
方法表达式
代码语言:javascript复制func main() {
u := User{1, "tioncico"}
u.Test()
fun1 := (User).Test
u.name="tioncico2"
fun1(u)
u.Test()
}
输出:
代码语言:javascript复制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}
其实可以看出,方法值为 "具体实例的方法",已经存在具体实例,需要通过实例去调用接收者方法,所以不需要额外传入接收者
而方法表达式为:"结构体的方法",需要额外传入结构体进行实际调用
其他
代码语言:javascript复制package main
import "fmt"
type User struct {
id int
name string
}
func (self *User) Test() {
fmt.Printf("%p,%vn", self, self)
}
func main() {
var u *User=nil
u.Test() //直接实例调用
(*User)(nil).Test() //方法值实例(实例值为nil)调用
(*User).Test(nil) //方法表达式,传入实例(实例为nil)调用
}
本文为仙士可原创文章,转载无需和我联系,但请注明来自仙士可博客www.php20.cn