Go Method Receiver 方法接收器介绍
Go 分类文章,学习笔记,会不定时修改,补充,纠错,增加内容,路漫漫。
Receiver 基本介绍
就是类似于 Class 的 Method,使用 this 或者 self 调用 ?可以这么类比吧,但是并不等同。
看具体的代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22type IntReceiver struct {
X int
}
// 方法接收器声明
func (i IntReceiver) Double() int {
return i.X * 2
}
// 普通函数声明
func IRDouble(i IntReceiver) int {
return i.X * 2
}
func main() {
i := IntReceiver{3}
d1 := i.Double() // 在 i 上调用了 IntReceiver 类型带的 Method // func (i IntReceiver) Double() int
fmt.Printf("type = %T,value = %v\n", d1, d1)
d2 := IRDouble(i) // 调用了普通函数 // func IRDouble(i IntReceiver) int
fmt.Printf("type = %T,value = %v\n", d2, d2)
}
定义 method 并不局限于结构体 struct,可以任何 type 声明的类型定义 Method,最简单如
type DInt int
,就能为 DInt 类型定义 method
方法值
接上文代码例子,第 17 行,i.Double
(注意没加括号) 叫作 “选择器”,选择器会返回一个 “方法值”-> 一个将方法 IntReceiver.Double
绑定到特定接收器变量的函数。这个函数可以不通过指定其接收器即可被调用,即调用时不需要指定接收器 。
1 | i := IntReceiver{4} |
方法表达式
方法值,其实还是指定了接收器的,在赋值的时候指定了 ,IntReceiverDouble := i.Double
,所以在调用的时候不需要指明。
方法表达式,不需要指出具体的变量,针对的是类型。
当 T 是一个类型时,方法表达式可能会写作 T.f
或者 (*T).f
,会返回一个函数 “值”,这种函数会将其第一个参数用作接收器,所以可以用通常的方式来对其进行调用。
1 | // 带参数的方法声明 |
基于指针的方法
上面介绍的,都是基于值的,当这个接受者变量本身比较大时,就可以用其指针而不是值来声明方法。
1 | // 基于指针的方法声明 |
Receiver 调用多种情况
查看代码
1 | i1 := &IntReceiver{1} |
- 不管你的 method 的 receiver 是指针类型还是非指针类型,都是可以通过指针 / 非指针类型进行调用的,编译器会帮你做类型转换。
- 对于接收器是指针的方法,通过值类型调用,其实是个语法糖,
编译器隐式的获取了它的地址
,前提是这个值能获取地址,不是临时变量- 对于接收器是值的方法,传入指针类型,Go 会默认根据指针找到值,一种翻译说法是
解引用
特别说明
1 | IntReceiver{5}.Double() // 正确 |
为什么 IntReceiver{6}.Triple()
是错的,因为 IntReceiver{6}
属于临时变量,不能寻址,不能直接调用,所以必须先赋值给一个变量,然后在调用。
接口方法调用规则
上文所述都是针对具体类型,具体类型完全适用。
但是对接口方法的调用,有点不同,具体规则如下
- 类型
*T
的可调用方法集包含接受者为*T
或T
的所有方法集 - 类型
T
的可调用方法集包含接受者为T
的所有方法 - 类型
T
的可调用方法集不包含
接受者为*T
的方法
1 | package main |
以上
总结完毕,Go 帮助程序员简化了很多指针的操作。
原文作者: dryyun
原文链接: https://dryyun.com/2018/12/14/go-method-receiver/
发布日期: 2018-12-14 16:28
许可协议: 知识共享署名-非商业性使用 4.0 国际许可协议