package main import "fmt" // 首先,Go中也有结构体,类似C++的struct/class,是面向对象的基础 type Person struct { // struct内部只有成员变量 name string } // 成员函数像这样定义在struct的外部,在前面自己定义类似this/self之类的变量 // 我们称之为「receiver」(这里就是p) // receiver只能是某种非指针类型(比如Person)或者其单层指针(*Person),多层是不行的 func (p *Person) setName(name string) { p.name = name } // 传值的成员函数 // func (p Person) setName(name string) { // p.name = name // } // 上面有两个setName函数,一个接受Person,一个接受*Person // 二者只能存在一个,调用的时候也没有区别(都是「p.setName」,没有「p->setName」) // 好像是Go自动做了转换(自动将传递进来的参数,或者说调用者,匹配receiver的类型,是否是指针) // 二者效果上的区别也很显然了,传值和传地址的区别 // 注意,关于是使用Person还是*Person,一般会有规定: // 所有的成员函数,必须统一,要么都使用Person,要么都使用*Person // 我觉得:不管什么情况,全用指针不就行了?不用担心复制效率的问题,统一 // 除了下面的一种情况 // 实际上这里不需要修改p的内容 // 但是为了统一还是使用了指针*Person func (p *Person) sayHi() { fmt.Println("Hi, I am", p.name) } func main() { p := Person{ name: "A", } p.setName("B") p.sayHi() // ce: cannot call pointer method setName on Person // 临时变量是不能取地址的,这时候receiver用指针就不方便了(当然,这不是什么重大缺陷) // Person{"X"}.setName("Y") // 但是注意,这样是可以的 // 临时变量取了地址,还可以正常使用 pp := &Person{"X"} pp.setName("Y") pp.sayHi() }