01
介绍
在 Golang 语言中,除了 main 和 init 函数之外,其他函数还可以接收一个或多个参数,并且 Golang 函数可以接收可变长度的参数,需要注意的是,当 Golang 函数接收可变长度的参数时,需要将可变长度参数放在所有接收参数的最后,实际上,可变长度参数是一个切片类型的参数。
Golang 语言中的函数还可以接收多个返回值,通常会用于返回 error 错误信息。
Golang 语言的函数是第一公民「first-class」,它允许函数赋值给变量,作为参数传递给其他函数,或从其他函数返回。
本文我们介绍 Golang 语言函数的高级使用方式,关于函数的基本使用方式,我们在之前的文章中已经介绍过,本文不再赘述。
匿名函数
所谓匿名函数,顾名思义就是没有定义函数名的函数,通常用于只需短期使用的函数。我们还可以将匿名函数赋值给一个变量,通过变量调用匿名函数。我们通过以下示例代码,演示匿名函数的使用方式。
匿名函数 - 无参数和返回值:
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/