若干编程语言中的闭包对比
最近面试有问到 Groovy 闭包的概念和作用,这里将通过对比与关联法,将 Groovy 闭包与 Python 的 lambda
、JavaScript 的匿名函数(或闭包)、以及 Go 语言中的闭包进行对比,实现举一反三,融会贯通的效果。
1. Groovy 闭包
- 定义:闭包(Closure)是一个代码块,可以捕获并记住其定义时的上下文,可以作为参数传递、赋值给变量、甚至延迟执行。
- 语法:使用
{}
定义,参数用->
分隔。
1 |
|
- 特点:
- 可以访问外部作用域中的变量(自由变量)。
- 支持默认参数
it
。 - 广泛用于集合操作、事件处理和 DSL 编写。
推荐阅读 groovy 闭包在 jenkins pipeline 中的应用示例 —— code-samples/project/groovy-closure/README.MD
2. Python 的 lambda
表达式
- 定义:
lambda
是 Python 中定义匿名函数的方式,主要用于简单的函数定义,通常用于函数式编程的场景,如 map、filter 等。 - 语法:使用
lambda
关键字定义,参数在冒号:
之前,表达式在之后。
1 |
|
- 特点:
lambda
表达式只能包含单个表达式,不能包含复杂的语句块。lambda
可以捕获其定义时的外部变量(闭包),但其功能和复杂性不如 Groovy 的闭包。- 在 Python 中,更常用的是普通的
def
定义的函数。
3. JavaScript 的匿名函数(或闭包)
- 定义:JavaScript 的匿名函数是一种没有名字的函数,可以直接定义和调用,常用于回调函数或立即执行函数表达式(IIFE)。当匿名函数捕获其外部作用域中的变量时,称为闭包。
- 语法:使用
function
关键字定义,或者在 ES6 之后使用箭头函数=>
。
1 |
|
- 特点:
- 可以捕获外部作用域的变量(闭包),这是 JavaScript 强大的特性之一。
- 广泛用于回调函数、事件处理、以及 IIFE(立即执行函数表达式)。
- 箭头函数(ES6)与普通函数不同,不绑定自己的
this
值,而是继承自外层作用域。
4. Go 语言中的闭包
- 定义:在 Go 语言中,闭包是指一个函数可以引用其外层函数的变量,甚至在外层函数执行完毕后,这些变量仍然可以被访问和修改。
- 语法:闭包通过函数嵌套定义实现。
1 |
|
- 特点:
- 闭包可以捕获并保留外层函数的变量,这使得它们在外层函数返回后仍然可用。
- 在并发场景中使用闭包需要特别小心,尤其是在闭包中修改共享变量时,需要考虑线程安全性。
- 闭包常用于工厂函数、延迟计算和事件处理。
总结对比
通用性: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/