Golang 表达式 :根据调用者不同,方法分为两种表现形式:
instance.method(args...) ---> <type>.func(instance, args...)
前者称为 method value,后者 method expression。
两者都可像普通函数那样赋值和传参,区别在于 method value 绑定实例,而 method expression 则须显式传参。
package main
import "fmt"
type User struct {
id int
name string
}
type Manager struct {
User//通过组合实现继承
title string
}
func (u *User) ToString() string {
return fmt.Sprintf("User: %p %v\n",u, u)
}
func (m *Manager) ToString() string {
return fmt.Sprintf("Manager: %p %v\n",m, m)
}
func (u *User) TestPointer() {
fmt.Printf("TestPointer %p,%v\n",u, u)
}
func (u User) TestValue(){
fmt.Printf("TestValue %p,%v\n",&u,u)
}
func main() {
m := Manager{User{1,"Tom"},"Administrator"}
fmt.Println(m.ToString())
fmt.Println(m.User.ToString())
fmt.Println("---------------------------------")
u := User{1,"Tom"}
u.TestValue()//u为{1,"Tom"}
uValue := u.TestValue//uValue为当前u的方法,复制了u的值
u.id,u.name = 2,"cat"//改变u的值
u.TestValue()//u为改变的值
uValue()//该方法为复制值的方法
/* out
TestValue 0xc0000040a8,{1 Tom}
TestValue 0xc0000040d8,{2 cat}
TestValue 0xc000004108,{1 Tom}
*/
fmt.Println("---------------------------------")
//总结:方法中的对象为值的拷贝,还是地址的传递,与方法本身的声明相关
//与调用方法传递的类型无关
//由于*T的方法包含了*T+T的方法所以可以调用
u1 := User{1,"Tom"}
fmt.Printf("u1 %p,%v\n",&u1,u1)
mv := User.TestValue
mv(u1)//由于方法有一个隐藏的this指针
//mv中的u1是对主函数中u1的值拷贝,地址并不相同
mp := (* User).TestPointer
mp(&u1)//mp中的u1与主函数中u1是同一个内存且地址相同
mp2 := (* User).TestValue
mp2(&u1)//mp2中的u1是对主函数中u1的值拷贝,地址并不相同
}