/ Go 语言函数变量详解 /
本文将全面讲解 Go 语言中的函数变量用法,内容包括:
- 函数变量基本用法
- 函数变量作参数
- 函数返回函数
- 函数闭包
- 回调函数
- 内置函数转换
- 函数类型实现接口
- 空函数变量
- 函数类型比较
1
一、函数变量基本用法
在 Go 语言中,函数可以赋值给变量,即函数变量。
1.1
1. 定义函数变量
定义一个函数变量:
var f func(int, int) int // 声明一个函数变量f
f 是一个函数类型的变量,接收两个 int 参数,返回一个 int。
1.2
2. 赋值函数
将一个函数赋值给 f:
/ Go 语言函数变量详解 / 本文将全面讲解 Go 语言中的函数变量用法,内容包括: 函数变量基本用法 函数变量作参数 函数返回函数 函数闭包 回调函数 内置函数转换 函数类型实现接口 空函数变量 函数类型比较 1 一、函数变量基本用法 在 Go 语言中,函数可以赋值给变量,即函数变量。 1.1 1. 定义函数变量 定义一个函数变量: var f func(int, int) int // 声明一个函数变量f f 是一个函数类型的变量,接收两个 int 参数,返回一个 int。 1.2 2. 赋值函数 将一个函数赋值给 f:
现在 f 包含了 add 函数。
1.3
3. 调用
像调用普通函数一样调用 f:
f(1, 2) // 调用f,即add函数
函数变量 f 可以像 add 函数一样调用。
2
二、函数变量作参数
函数变量可作为参数传递给其他函数。
2.1
1. 声明类型
定义一个接收函数类型参数的函数:
func foo(f func(int, int) int) { // 函数体 }
foo 接收一个符合声明的函数类型参数 f。
2.2
2. 传递函数
调用时传递函数:
func add(a, b int) int { return a + b } func main() { foo(add) // 将add函数作为参数 }
这样就将 add 作为参数传给了 foo。
2.3
3. 调用
在 foo 中可以调用 f 函数:
func foo(f func(int, int) int) { result := f(1, 2) // 调用f fmt.Println(result) }
传入不同的函数变量,可以产生不同的结果。
3
三、函数返回函数
Go 语言中函数可以返回一个函数类型。
3.1
1. 返回函数类型
定义一个返回函数类型的函数:
func foo() func(int, int) int { // 返回函数 }
foo 返回一个符合声明的函数类型。
3.2
2. 返回函数
实现函数,返回某个函数:
func add(a, b int) int { return a + b } func foo() func(int, int) int { return add // 返回add }
3.3
3. 调用
调用时像使用函数一样:
f := foo() // 获取返回函数 result := f(1, 2) // 使用返回的函数
返回的函数可以赋值并执行。
4
四、函数闭包
函数内部可以引用外部的变量,形成闭包结构。
4.1
1. 闭包函数
func outer() func() int { x := 0 return func() int { x++ return x // 使用外部x } }
outer()返回一个闭包,引用了外部的 x 变量。
4.2
2. 调用闭包
f := outer() // 获取闭包 fmt.Println(f()) // 1 fmt.Println(f()) // 2 f2 := outer() // 重新执行outer fmt.Println(f2()) // 1
每次调用 outer()会生成一个新的 x 变量,并作用于闭包。
4.3
3. 修改外部变量
闭包函数可以修改外部变量:
func outer() func() { x := 0 return func() { x++ fmt.Println(x) } }
闭包可修改外部 x 的值。
5
五、回调函数
函数变量可以用作回调函数,实现异步模型。
5.1
1. 回调函数类型
定义一个接收回调函数参数的函数:
func foo(cb func(int)) { // 函数体 }
5.2
2. 传递回调
调用时传递回调函数:
func bar(n int) { fmt.Println("bar:", n) } func main() { foo(bar) // 传递bar作为回调函数 }
3. 执行回调
在 foo 内部调用回调 cb:
func foo(cb func(int)) { // ... cb(10) // 执行回调函数 }
回调函数实现了异步编程模型。
6
六、内置函数转换
Go 语言内置有将其他类型转换为函数的方法。
6.1
1. func(x int) int
将 int 类型转为等价的函数:
f := func(x int) int { return x }
等价于直接传 int:
f := 10 // f现在是一个函数类型 f(8) // 返回8
6.2
2. func(x T) *T
接收 T 类型参数,返回*T 类型结果:
f := func(x *int) *int { return x }
等价于:
var i int f := i // f现在是上述函数类型
6.3
3. 使用
这些转换可用于需要函数类型的场景:
var fs []func(int) int fs = append(fs, 10, 20, 30) // 添加整数,会转为函数
7
七、函数类型实现接口
函数类型可以实现接口。
7.1
1. 接口定义
定义一个函数类型的接口:
type Operator interface { Operate(int, int) int }
2. 实现接口
函数类型可以直接实现该接口:
func add(a, b int) int { return a + b } func main() { var o Operator o = add // add匹配接口 }
7.3
3. 调用
调用接口方法会执行函数:
result := o.Operate(1, 2) // 执行add函数
将函数作为接口实现可以减少额外的封装。
8
八、空函数变量
空的函数变量需要特殊注意。
8.1
1. 空函数变量
声明一个函数变量但不赋值:
var f func(int)
这时 f 是一个空函数变量。
8.2
2. 空指针
空函数变量在内存中是一个 nil 指针。
必须先判断是否为 nil:
if f != nil { f(10) }
8.3
3. 初始化
需要初始化函数变量才能使用:
f = func(x int) { // ... }
使用未初始化的函数变量会 panic。
9
九、函数类型比较
Go 语言中函数还可以进行比较。
9.1
1. 相同类型
两个相同类型的函数变量可以比较:
func add(int, int) int func sub(int, int) int var f1, f2 func(int, int) int f1 = add f2 = sub fmt.Println(f1 == f2) // false
9.2
2. 不同类型
如果两个函数类型不同,不能比较:
func add(int, int) int func sub(float64, float64) float64 var f1, f2 func(int, int) int f1 = add f2 = sub // 无法比较
9.3
3. nil 函数
nil 函数也可以比较:
var f1 func(int) if f1 == nil { // f1是nil }
10
十、总结
Go 语言中函数是一类独立的类型,支持赋值、传参、返回函数变量。
可以利用这一特性实现函数回调、闭包相关的功能。
需要注意空函数变量和比较函数类型的规则。
熟练运用函数类型可以编写非常灵活的代码。