若干编程语言中的闭包对比

最近面试有问到 Groovy 闭包的概念和作用,这里将通过对比与关联法,将 Groovy 闭包与 Python 的 lambda、JavaScript 的匿名函数(或闭包)、以及 Go 语言中的闭包进行对比,实现举一反三,融会贯通的效果。

1. Groovy 闭包

  • 定义:闭包(Closure)是一个代码块,可以捕获并记住其定义时的上下文,可以作为参数传递、赋值给变量、甚至延迟执行。
  • 语法:使用 {} 定义,参数用 -> 分隔。
1
2
3
4
def greet = { name -> 
return "Hello, ${name}!"
}
println(greet("Zhi")) // 输出:Hello, Zhi!
  • 特点
    • 可以访问外部作用域中的变量(自由变量)。
    • 支持默认参数 it
    • 广泛用于集合操作、事件处理和 DSL 编写。

推荐阅读 groovy 闭包在 jenkins pipeline 中的应用示例 —— code-samples/project/groovy-closure/README.MD

2. Python 的 lambda 表达式

  • 定义lambda 是 Python 中定义匿名函数的方式,主要用于简单的函数定义,通常用于函数式编程的场景,如 map、filter 等。
  • 语法:使用 lambda 关键字定义,参数在冒号 : 之前,表达式在之后。
1
2
greet = lambda name: f"Hello, {name}!"
print(greet("Zhi")) # 输出:Hello, Zhi!
  • 特点
    • lambda 表达式只能包含单个表达式,不能包含复杂的语句块。
    • lambda 可以捕获其定义时的外部变量(闭包),但其功能和复杂性不如 Groovy 的闭包。
    • 在 Python 中,更常用的是普通的 def 定义的函数。

3. JavaScript 的匿名函数(或闭包)

  • 定义:JavaScript 的匿名函数是一种没有名字的函数,可以直接定义和调用,常用于回调函数或立即执行函数表达式(IIFE)。当匿名函数捕获其外部作用域中的变量时,称为闭包。
  • 语法:使用 function 关键字定义,或者在 ES6 之后使用箭头函数 =>
1
2
3
4
5
6
7
8
// 匿名函数
const greet = function(name) {
return "Hello, " + name + "!";
};
console.log(greet("Zhi")); // 输出:Hello, Zhi!

const greetArrow = (name) => `Hello, ${name}!`;
console.log(greetArrow("Zhi")); // 输出:Hello, Zhi!
  • 特点
    • 可以捕获外部作用域的变量(闭包),这是 JavaScript 强大的特性之一。
    • 广泛用于回调函数、事件处理、以及 IIFE(立即执行函数表达式)。
    • 箭头函数(ES6)与普通函数不同,不绑定自己的 this 值,而是继承自外层作用域。

4. Go 语言中的闭包

  • 定义:在 Go 语言中,闭包是指一个函数可以引用其外层函数的变量,甚至在外层函数执行完毕后,这些变量仍然可以被访问和修改。
  • 语法:闭包通过函数嵌套定义实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import "fmt"

func greet(name string) func() string {
return func() string {
return "Hello, " + name + "!"
}
}

func main() {
sayHello := greet("Zhi")
fmt.Println(sayHello()) // 输出:Hello, Zhi!
}
  • 特点
    • 闭包可以捕获并保留外层函数的变量,这使得它们在外层函数返回后仍然可用。
    • 在并发场景中使用闭包需要特别小心,尤其是在闭包中修改共享变量时,需要考虑线程安全性。
    • 闭包常用于工厂函数、延迟计算和事件处理。

总结对比

  • 通用性:Groovy、Python、JavaScript 和 Go 的闭包/匿名函数都能捕获外部变量,使函数的功能更加灵活和强大。它们都广泛应用于回调函数、事件处理和延迟计算等场景。

  • 功能复杂度:Groovy 和 JavaScript 的闭包功能较为强大,支持复杂的操作和语法糖。Python 的 lambda 更适合简单场景,而复杂的逻辑通常使用 def 定义的函数。Go 的闭包则在编写高并发程序时提供了强大的能力,但需要注意线程安全。

  • 语法差异:不同语言的闭包/匿名函数在语法上各具特色,Groovy 使用 {} 定义,Python 使用 lambda,JavaScript 有 function=>,而 Go 使用嵌套函数。

通过这些对比,利用已有的语言知识,更容易理解 Groovy 闭包的概念和作用。


若干编程语言中的闭包对比
https://github.com/zhililab/2024/08/29/Learning-Golang-004/
作者
Zhi Li
发布于
2024年8月29日
许可协议