01 介绍
在 Golang 语言中,除了 main 和 init 函数之外,其他函数还可以接收一个或多个参数,并且 Golang 函数可以接收可变长度的参数,需要注意的是,当 Golang 函数接收可变长度的参数时,需要将可变长度参数放在所有接收参数的最后,实际上,可变长度参数是一个切片类型的参数。
Golang 语言中的函数还可以接收多个返回值,通常会用于返回 error 错误信息。
Golang 语言的函数是第一公民「first-class」,它允许函数赋值给变量,作为参数传递给其他函数,或从其他函数返回。
本文我们介绍 Golang 语言函数的高级使用方式,关于函数的基本使用方式,我们在之前的文章中已经介绍过,本文不再赘述。
02 匿名函数
所谓匿名函数,顾名思义就是没有定义函数名的函数,通常用于只需短期使用的函数。我们还可以将匿名函数赋值给一个变量,通过变量调用匿名函数。我们通过以下示例代码,演示匿名函数的使用方式。
匿名函数 - 无参数和返回值:
func TestAnonymous(t *testing.T) {
func () {
t.Log("Hello World")
}()
}
匿名函数 - 有参数和返回值:
func TestAnonymous(t *testing.T) {
func (a, b int) int {
return a + b
}(1,2)
}
匿名函数 - 赋值给变量:
func TestAnonymous(t *testing.T) {
sum := func (a, b int) int {
return a + b
}
t.Log(sum(1, 2))
}
03 闭包
在 Golang 语言中,函数支持匿名函数,闭包就是一种特殊的匿名函数,它可以用于访问函数体外部的变量。
示例代码:
func TestClosures(t *testing.T) {
x, y := 1, 2
func (a, b int) {
t.Log(a + b)
}(x, y)
}
需要注意的是,在 for ... range ...
中,使用协程执行闭包时,经常会掉「坑」。因为匿名函数可以访问函数体外部的变量,而 for ... range ...
返回的 val 的值是引用的同一个内存地址的数据,所以匿名函数访问的函数体外部的 val 值会是循环中最后输出的一个值。
示例代码:
func TestClosures(t *testing.T) {
values := []int{1,2,3,4,5}
for _, val := range values {
go func() {
t.Logf("%p %d\n", &val, val)
}()
}
time.Sleep(time.Second)
}
避「坑」的方法是使用闭包函数传递参数,示例代码如下:
func TestClosures(t *testing.T) {
values := []int{1,2,3,4,5}
for _, val := range values {
go func(val int) {
t.Logf("%p %d\n", &val, val)
}(val)
}
time.Sleep(time.Second)
}
04 递归
在 Golang 语言中,也支持递归函数。需要注意的是,使用闭包递归,需要在定义闭包之前,显式声明闭包。
示例代码:
func TestRecursion(t *testing.T) {
var fib func(n int) int
fib = func (n int) int {
if n < 2 {
return n
}
return fib(n - 1) + fib(n -2)
}
t.Log(fib(7))
}
05 自定义函数类型
在 Golang 语言中,我们也可以像定义结构体类型一样,定义函数类型。
示例代码:
type sum func(int, int) int
自定义的函数类型,可以作为高阶函数的参数或返回值。
06 高阶函数
高阶函数是接收参数或返回值是函数类型的变量的函数,也就是说高阶函数是操作其他函数的函数。
函数作为参数:
func TestHigherOrder(t *testing.T) {
t.Log(operation(1, 2, func(x, y int) int {
return x + y
}))
}
func operation(x, y int, operaFuc func(int, int) int) int {
rst := operaFuc(x, y)
return rst
}
函数作为返回值:
func TestHigherOrder(t *testing.T) {
sum := operation1()
t.Log(sum(2, 3))
}
func operation1() func(x, y int) int {
sum := func(x, y int) int {
return x + y
}
return sum
}
07 总结
本文我们介绍了 Golang 语言中函数的高级使用方式,包含匿名函数、闭包、递归、自定义函数类型和高阶函数,并分别列举了一个简单示例,感兴趣的读者朋友,可以在本地运行示例代码,并通过修改调式代码,加深理解。
参考资料: https://gobyexample.com/closures https://gobyexample.com/recursion https://zetcode.com/golang/function/ https://golangbot.com/first-class-functions/ https://www.golangprograms.com/go-language/functions.html https://golangbyexample.com/function-golang-complete-guide/