高级函数的使用细节
一 函数签名的概念
一个函数签名 (或类型签名,或方法签名) 定义了函数或方法的输入与输出。
简单的说: 函数的签名就是函数的参数列表与返回值列表的统称。使用签名可以鉴别不同函数的特征,此外,也定义了用户与函数直接交互的方法。
特别说明:
1 参数的名称和返回值的名称,不作为函数签名的一部分。换句话说,就是签名与参数的名称无关。
2 只要两个函数参数列表和返回值列表元素的顺序与类型是一致,就可以说明该两个函数是一样的函数或者说实现了同一个类型函数。
例如:
1 | // 自定义函数类型 |
可以说明TestFunc是对MyFuncType自定义函数类型的一种实现,它们是一种类型的函数。
二 Go中函数是一等的公民
- 封装代码
- 分割功能
- 解耦逻辑
- 做为普通的值,函数当作参数在其他函数中传递、能将函数赋值变量
- 能够进行类型判断和转换
三 匿名函数
定义:没有函数名称的函数,称为匿名函数;
1. 匿名函数可以直接复制给变量,然后通过变量进行调用;
1 | func main() { |
2. 匿名函数也可以在定义好后的**} 后面直接添加(函数签名)**进行调用
1 | func main() { |
四 自定义函数类型
使用 type关键词自定义函数类型;
1 | // 自定义函数类型 |
五 高阶函数
函数作为参数传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26package main
import (
"errors"
"fmt"
)
// 自定义函数类型,操作类型
type operate func(x, y int) int
func Mixer(x, y int, op operate) (int, error) {
if op == nil {
return 0, errors.New("操作类型错误")
}
return op(x, y), nil
}
func main() {
var op operate = func(x, y int) int {
return x + y
}
var x, y = 23, 43
// 将函数作为参数,控制函数的行为,将无状态变有状态.只要对operate类型函数进行实现,就可以实现不同逻辑。定向输出。
result , error := Mixer(x, y, op)
fmt.Println(result, error)
}函数作为返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34package main
import (
"errors"
"fmt"
)
// 定义一个需要返回的函数类型,接受两个int类型参数,返回一个int类型
type GetValue func(x, y int) (int, error)
// 自定义操作类型
type Operate func(x, y int) int
// 定义一个返回GetValue函数的函数
func Calculate(op Operate) GetValue {
return func(x, y int) (int, error) {
// 如果操作符为nil,则抛出错误
if op == nil {
return 0, errors.New("invalid operate error")
}
// 否则,调用操作函数
return op(x, y), nil
}
}
func main() {
var op = func(x, y int) int{
return x * y
}
var a, b = 5, 10
result := Calculate(op)
data, error := result(a, b)
fmt.Println(data, error)
}
六 闭包
闭包是在函数中嵌套定义函数,并且在内部函数中,使用到外部函数传入的自由变量,在函数内部获取了访问外部函数参数的权限,并进行逻辑的处理。外部函数返回的一般是内部函数的地址。
例如:
1 | func Outfunction(x int) func(int) int { |
闭包的价值在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅要表示数据还要表示代码。将函数作为第一级对象,就是说这些函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建和返回。
七 头等(第一类)函数的使用场景
头等函数就是上面提到的能够支持高阶函数的用法,能够将函数作为其他函数的参数或返回值。
将函数进行传递,根据函数的多样性去确定结果的唯一性。