Go - Function
声明
image-20231111162657319
- 关键字
func
- Go 函数声明必须以关键字 func 开始
- 函数名
- 在
同一个 Go 包
中,函数名应该是唯一
的 - 遵循 Go 标识符的
导出
规则
- 在
- 参数列表
- Go 函数支持
变长参数
,即一个形式参数
对应多个实际参数
- Go 函数支持
- 返回值列表
- 支持
具名返回值
,比较少用
- 支持
- 函数体
- 可选,如果
没有函数体
,说明该函数可能在Go 语言之外
实现的 - 可能使用
汇编语言
,然后通过链接器将实现与声明中的函数名链接在一起
- 可选,如果
类比
将
函数声明
等价转换为变量声明
的形式 - 声明一个类型为函数类型
的变量
image-20231111163953587
Key | Value |
---|---|
变量名 | 函数名 |
函数签名 |
参数列表 + 返回值列表 |
函数类型 |
func + 参数列表 + 返回值列表 func + 函数签名 |
函数签名
:决定两个函数类型是否相同
- 在表述
函数类型
时,通常会省略
函数签名参数列表中的参数名
,以及返回值列表中的返回值变量名
go
1 | // 函数类型,只关注入参和出参 |
相同的函数签名,相同的函数类型
go
1 | func (a, b int) (res []string, err error) |
每个
函数声明
所定义的函数,仅仅是对应函数类型
的一个实例
字面量
go
1 | package main |
在 Go 中,在大部分时候,还是会通过
函数声明
来声明一个特定函数类型
的实例
go
1 | // 本质上是声明了一个函数类型为 func(int, int) int 的变量 sum |
参数
- 函数列表中的
参数
,是函数声明的,用于函数体实现的局部变量
- 在
函数声明
阶段,称为形式参数
;在函数调用
阶段,传入的参数称为实际参数
- 在实际调用函数时,
实际参数
会传递给函数,并且与形式参数
逐一绑定
编译器
会根据各个形式参数的类型
和数量
,来检查实际参数的类型和数量,是否匹配
- 如果不匹配,编译器会报错
image-20231111170620385
值传递
函数参数传递采用的是
值传递
的方式,将实际参数
在内存中的表示,逐位拷贝
(Bitwise Copy)到形式参数
中
类型 | 拷贝 | 描述 |
---|---|---|
int 、array 、struct |
深 拷贝 |
内存表示为数据本身 ,值传递开销与数据大小 成正比 |
string 、slice 、map |
浅 拷贝 |
内存表示为数据的描述符 ,值传递开销固定 |
例外
简单的值传递不能满足需求,
编译器
需要介入
接口类型
编译器将传递的实际参数
赋值
给对应的接口类型形式参数
变长参数
变长参数是通过
切片
来实现的
go
1 | package main |
多返回值
Go 的
错误处理机制
很大程度上是建立在多返回值
的机制上
go
1 | func foo() |
具名返回值
- 支持
具名返回值
(Named return value),可以像函数体
中声明的局部变量
一样,在函数体内使用 - 具名返回值仅应用于
特定场景
- 在函数中使用
defer
,并且还在 defer 函数中修改包裹函数的返回值
- 当函数
返回值较多
时,使用具名返回值可以增强可读性
- 在函数中使用
go
1 | func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) { |
一等公民
具有极大的
灵活性
- 如果一门编程语言对某种
语言元素
的创建和使用没有限制
,可以像对待值
一样对待这种语言元素 - 可以
存储在变量
中,可以作为参数
传递给函数
,可以在函数内部
创建并作为返回值
从函数返回
特征
变量
go
1 | var ( |
返回值
go
1 | package main |
闭包
本质上是一个匿名函数
(函数字面量),可以引用它的包裹函数
中定义的变量
- 这些变量在
包裹函数
和匿名函数
之间共享
- Go 的
闭包特性
是建立在函数是一等公民
的基础上
参数
go
1 | // AfterFunc waits for the duration to elapse and then calls f |
类型
每个
函数声明
定义的函数,仅仅只是对应的函数类型
的一个实例
基于
函数类型
来自定义类型
go
1 | // The HandlerFunc type is an adapter to allow the use of |
go
1 | type visitFunc func(ast.Node) ast.Visitor |
应用
函数类型
函数是
一等公民
,拥有对应的类型
,可以被显式转型
(前提是底层类型
要一致)
go
1 | // greeting 是一个函数,它的类型是 func(http.ResponseWriter, *http.Request) |
go
1 | func ListenAndServe(addr string, handler Handler) error { |
闭包
简化函数调用
,闭包是函数内部创建的匿名函数
,可以访问包裹函数
的参数
和局部变量
go
1 | func times(x, y int) int { |
通过
闭包
简化函数调用,减少参数的重复输入
go
1 | func times(x, y int) int { |
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.