- 如何选择方法的receiver类型:要修改实例状态,用 *T;无须修改状态的小对象或固定值,建议用T;大对象建议用 *T,以减少复制成本;引用类型、字符串、函数等指针包装对象,直接用T;若包含Mutex等同步字段,用 *T,避免因复制造成锁操作无效;其他无法确定的情况,都用 *T
- 方法集:类型T方法集包含所有receiver T方法;类型*T方法集包含所有receiver T + *T 方法;匿名嵌入S,T方法集包含所有receiver S方法;匿名嵌入 *S,T方法集包含所有receiver S + *S方法;匿名嵌入 S 或 *S,*T方法集包含所有receiver S + *S方法
- 方法和函数一样,除直接调用外,还可赋值给变量,或作为参数传递。依照具体引用方式的不同,可分为expression和value两种状态
3.1 通过类型引用的method expression会被还原为普通函数样式,receiver是第一参数,调用时必须显式传参type N int func (n N) test() { fmt.Printf("test.n:%p,%d\n",&n,n) } func main() { var n N = 25 fmt.Println("main.n:%p,%d\n",&n,n) f1:=N.test //func(n N) f1(n) f2:=(*N).test //func(n *N) f2(&n) //按方法集中的签名传递正确类型的参数 } // 输出: // main.n:0xc82000a140,25 // test.n:0xc82000a158,25 // test.n:0xc82000a168,25 // 尽管 *N方法集包装的test方法receiver类型不同,但是编译器会保证按原定义类型拷贝传值
- 只能为当前包内命名类型定义方法
- 可以像字段成员那样访问匿名字段方法,编译器负责查找
type User struct { id int name string } type Manager struct { User } func (self *User) ToString() string { // receiver = &(Manager.User) return fmt.Sprintf("User: %p, %v", self, self) } func main() { m := Manager{User{1, "Tom"}} fmt.Printf("Manager: %p\n", &m) fmt.Println(m.ToString()) } // Manager: 0x2102281b0 // User : 0x2102281b0, &{1 Tom}
go 方法 —— 摘自go语言学习笔记
最新推荐文章于 2023-01-13 23:31:02 发布