Go编程基础——方法method

方法method
1、Go 中 虽 没 有 class , 但 依 旧 有 method
2、通 过 显 示 说 明 receiver 来 实 现 与 某 个 类 型 的 组 合
3、只 能 为 同 一 个 包 中 的 类 型 定 义 方 法
4、Receiver 可 以 是 类 型 的 值 或 者 指 针
5、不 存 在 方 法 重 载
6、 可 以 使 值 或 指 针 来 调 用 方 法, 编 译 器 会 自 动 完成转换
7、从 某 种 意 义 上 来 说 , 方 法 是 函 数 的 浯 法 糖 , 因 为 receiver 其 实 就 是
方 法 所 接 收 的 第 1 个 参 数 ( Method Value vs. Method Expression )
8、如 果 外 部 结 构 和 嵌 入 结 构 存 在 同 名 方 法 , 则 优 先 调 用 外 部 结构的 方 法
9、类 型 别 名 不 会 拥 有 底 层 类 型 所附带 的 方 法
10、 方 法 可 以 调 用 结 构 中 的 非 公 开 字 段

首先思考如何为一个函数写方法method,是通过receiver。根据接收者的类型来判断方法是来自哪个结构体

type Aa struct{
   name string
}
type Bb struct{
   name string
}

func main() {
a:=Aa{}
a.print()
a.sayHello("China")
}
func (a Aa)print(){
   fmt.Println("Aa")
}
func (b Aa)sayHello(w string)  {
   fmt.Println(w)
}

运行结果

Aa
China

首先来看方法print,局部变量a的接受者Aa,方法的名称是print。在main方法中首先声明一个结构a,这就可以使用接受者来判断这个结构体有哪些方法,这里是有print方法在结构体Aa中。通过接收者类型Aa就这样把结构体Aa和方法print链接在一起。
Go语言中不存在方法的重载,是指同一个类型的结构体,不同的结构体存在相同的方法名是允许的。看如下程序:

func (a Aa)print(){
   fmt.Println("Aa")
}
func(a Aa)print(i int){
   fmt.Println("Aa in override")
}

这样编译器会报错,这里的print()和print(i int)的接收者都是Aa结构体,所以这样就构成了方法的重载,这是在Go语言中没有实现的底层机制,换句话说就是不允许方法重载。

method redeclared 'Aa.print' less... (Ctrl+F1)
Reports names redeclared in this block.

但是不同的结构体方法名相同是可以的。

type Aa struct{
   name string
}
type Bb struct{
   name string
}

func main() {
a:=Aa{}
a.print()
b:=Bb{}
b.print()
}
func (a Aa)print(){
   fmt.Println("Aa")
}
func (b Bb)print(){
   fmt.Println("Bb")
}

运行结果

Aa
Bb

接收者不一样,方法名相同不算构成方法重载,这是允许的

这里的接收者是作为第一个参数传递,就要搞清楚是值传递还是指针传递这个问题。

type Aa struct{
   name string
}
type Bb struct{
   name string
}

func main() {
a:=Aa{}
a.print()
fmt.Println(a.name)
b:=Bb{}
b.print()
fmt.Println(b.name)
}
func (a *Aa)print(){
   a.name="AAA"
   fmt.Println("Aa")
}
func (b Bb)print(){
   b.name="BBB"
   fmt.Println("Bb")
}

运行结果

Aa
AAA
Bb

首先第一个print()使用的是指针传递,第二个print()使用的不带指针的传递,从结果可以看出接收者也是服从一般的参数传递规则的,指针传递就会改变原来内存地址对应的值,值传递则不会改变变量的值。这里也可以看出Go语言是通过自动判断使用的指针传递还是值传递,有程序为例,前边

func (a Aa)print(){
   fmt.Println("Aa")
}

和后边的

func (a *Aa)print(){
   a.name="AAA"
   fmt.Println("Aa")
}

相比,后边的传递是指针传递,但最后两种的调用都是一样的使用

a:=Aa{}
a.print()

Go语言底层自动识别和判断。
接下来是类型别名和方法的组合的应用

type TZ int
func main() {
var a TZ
a.print()
}
func (a *TZ)print(){
   fmt.Println("func of TZ")
}

运行结果

func of TZ

这样通过type实现一个方法的绑定,这样的int对应的TZ只能在这个包内找到对应的方法。
Method Value vs. Method Expression
看如下程序

type TZ int
func main() {
var a TZ
a.print()
(*TZ).print(&a)
}
func (a *TZ)print(){
   fmt.Println("func of TZ")
}

运行结果

func of TZ
func of TZ

注意到对于(*TZ)来说,a代表的是指针,这里就需要取它的地址符号才能获取值,这也是Method Value和Method Expression表达上的不同,结果是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值