Golang的闭包和匿名函数
2023-12-16 13:44 abce 阅读(220) 评论(0) 编辑 收藏 举报Golang语言支持匿名函数,这些匿名函数也被称为闭包。匿名函数是一种特殊类型的函数,它没有名称,而闭包可以看作是一种特殊类型的匿名函数,尽管在实践中有微小的区别。
Golang 中的匿名函数
匿名函数也可以称为字面函数、lambda 函数或闭包。闭包的概念源于 lambda 计算中表达式的数学评估。从技术上讲,匿名函数和闭包之间有一个微妙的区别:匿名函数是一个没有名称的函数,而闭包是一个函数的实例。然而,要在 Golang 中实际实现闭包,编写匿名函数是关键。
如何创建闭包
通过匿名函数,我们可以在任何表达式中编写表示函数值的字面函数。其语法与命名的函数(常规函数)非常相似,只是在 func 关键字之后没有名称。因此,如果 Go 开发人员不想给函数命名,那么我们可以创建匿名函数。
以下是在 Go 中创建闭包的语法和示例代码:
func (a, b int){ return a+b }
请注意,这种函数不能单独编写,因此在赋值时要声明一个变量,如:
sum := func(a, b int) int { return a + b } fmt.Println(sum(1, 2))
函数的调用方式为 sum(1,2)。
也可以在定义时直接调用,如下所示:
sum := func(a, b int) int { return a + b }(1, 2) fmt.Println(sum)
下面是另一个求整数之和的示例
--在这个代码示例中,我们可以将匿名函数编写如下:
func() { sum := 0 for i := 0; i < 100; i++ { sum += i } }()
func 关键字后的第一个括号 () 是参数列表,闭包没有名称。闭包的主体由大括号 {} 组成,最后一对小括号 () 表示函数调用。
闭包如何返回值
闭包或匿名函数可以创建带参数或不带参数的函数,但我们能从这样的函数中返回值吗?
下面是一个如何从 Go 中的闭包返回值的示例。让我们编写一个函数,每次调用都返回下一个斐波那契数字:
package main import "fmt" func fibonacci() func() int { a, b := -1, 1 return func() int { a, b = b, a+b return b } } func main() { fibo := fibonacci() for i := 0; i < 10; i++ { fmt.Println(fibo()) } }
函数返回另外一个函数
已声明的局部变量的作用域有限,只存在于声明该变量的程序块或函数中。
当变量失去作用域时,就会被刷出内存。不过,在闭包的帮助下,即使在执行程序离开代码块后,局部变量仍有可能继续存在。我们可以使用 Go 闭包编写一个返回另一个函数的函数。下面是一个例子:
func square() func(num int) int { return func(num int) int { return num * num } } func mul(n1 int) func(n2 int) int { return func(n2 int) int { return n1 * n2 } } func main() { // make an square function, give it a name f2, and call it: f2 := square() fmt.Printf("Call square for 3 gives: %v\n", f2(3)) // make a special mul function, n1 gets value 3: f3 := mul(3) fmt.Printf("The result is: %v\n", f3(3)) }
将匿名函数作为参数传递
下面的示例程序说明了如何在 Go 中将匿名函数作为参数传递给另一个函数。同时请注意,匿名函数在变量上闭包,形成一个闭包:
package main import ( "fmt" "math/rand" "time" ) func xyValues(f func(max int) (int, int)) { x, y := f(35) fmt.Println(x, y) x, y = f(50) fmt.Println(x, y) } func main() { fn := func(max int) (int, int) { r := rand.New(rand.NewSource(time.Now().UnixNano())) x_axis := r.Intn(max) y_axis := r.Intn(max) return x_axis, y_axis } xyValues(fn) x, y := fn(20) fmt.Println(x, y) }
在上述代码示例中,匿名函数是在主函数中声明的。它只是在作为函数参数传入的最大值范围内,为 x_axis 和 y_axis 生成两个随机整数,并返回。
匿名函数被赋值给变量 fn,并将函数值传递给另一个名为 xyValues 的函数。xyValues 函数反过来接收一个函数作为参数,即 fn 函数参数。
有几点需要注意:在 main 中,匿名函数的值有两个用途:
·将函数值作为参数传递,调用 xyValues 函数。
·通过提供一个值作为参数,直接调用函数值。