Go 中虽没有class,但依旧有method
通过显示说明receiver来实现与某个类型的组合
只能为同一个包中的类型定义方法
Receiver 可以是类型的值或者指针
不存在方法重载
可以使用值或指针来调用方法,编译器会自动完成转换
从某种意义上来说,方法是函数的语法糖,因为receiver其实就是
方法所接收的第1个参数(Method Value vs. Method Expression)
如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法
类型别名不会拥有底层类型所附带的方法
方法可以调用结构中的非公开字段
package main
import (
"fmt"
)
type A struct {
Name string
}
type B struct {
Name string
}
func main() {
a := A{} //声明一个结构A,类似于PHP的$a = new A();操作
a.Print() //然后调用一个A结构的方法
}
//为A结构写方法
//编译器通过receiver接收者来判断是哪个结构类型的方法
//该方法与A结构联系到一起,及附属在A结构上
func (a A) Print() { //(a A就是func的第一个参数,即receiver,a为struct对象的接收者,可以值传递和引用传递,变量结构类型为A,方法名称为Print,Print里的参数和返回类型可有可无。func (a A) Print()和func (a *A) Print(),两者不能同时存在,因为函数名相同
fmt.Println("我是A结构体的Print方法输出的。")
}
输出:
我是A结构体的Print方法输出的。
package main
import (
"fmt"
)
type A struct {
Name string
}
type B struct {
Name string
}
func main() {
a := A{}
a.Print()//虽然这里是指针传递,但是调用的使用a前面不要加&, ,因为Go知道receiver是指针,他自动帮你转了
//类似的如果一个method的receiver是T,你可以在一个*T类型的变量P上面调用这个method,而不需要 *P去调用这个method。所以,你不用担心你是调用的指针的method还是不是指针的method,Go知道你要做的一切,这对于有多年C/C++编程经验的同学来说,真是解决了一个很大的痛苦。
fmt.Println()
b := B{}
b.Print()
fmt.Println()
}
//很显然,指针传递的可以使原来的值发生改变,而值传递的就不会了
//说明receiver还是遵循参数规则
func (a *A) Print() {
= "AA"
fmt.Println("我是A结构体的Print方法输出的。")
}
func (b B) Print() {
= "BB"
fmt.Println("我是B结构体的Print方法输出的。")
}
输出:
我是A结构体的Print方法输出的。
AA
我是B结构体的Print方法输出的。
值传递和指针传递
package main
import (
"fmt"
)
//类型别名
//类似于给int定义一个别名,但是此时的TZ与struct定义的类型使用方法一样,把它当作一个类,可以为其添加方法
type TZ int//注意这不是一个结构体,用了底层类型int整型
func main() {
//接收者为typeName,而不是*typeName时,调用方法varName.funcName(param)与typeName.funcName(varName, param)一样,如果是*typeName 则不能后者访问
//接收者为 *typeName时,通过varName.funcName()访问时,等于(&varName).funcName(),即可以不用在varName前面加上"&"取地址
var a TZ
a.Print("我是非指针打印!")//官方称为:Method Value
TZ.Print(a, "我是非指针打印!")//官方称为:Method Expression
a.pointerPrint("我是指针打印!")//官方称为:Method Value
}
func (a TZ) Print(s string) {
fmt.Println(s)
}
func (a *TZ) pointerPrint(s string) {
fmt.Println(s)
}
输出:
我是非指针打印!
我是非指针打印!
我是指针打印!
访问权限
package main
import (
"fmt"
)
//访问权限
type A struct {
name string //注意这时的name首字母为小写,即私有属性
}
//注意:我们所说的首字母大小写的公私有权限问题,是以package为界限的,针对包外的,即除了该main包意外的包,而在包里不管大小写都是可以访问的
func main() {
a := A{}
a.Print()
fmt.Print() //成功输出,说明main函数也能访问结构体私有属性
}
func (a *A) Print() {
= "GO"
fmt.Println() //成功输出,说明方法可以访问结构体的私有属性
}
GO
GO
















