Golang中函数变量比普通函数执行更快吗?
Golang中函数变量比普通函数执行更快吗? 我在做一道 LeetCode 题目时,发现这段代码:
func floodFill(image [][]int, sr int, sc int, color int) [][]int {
original :=image[sr][sc]
if original == color {
return image
}
fill(image, sr, sc, color, original)
return image
}
func fill(image [][]int, sr int, sc int, color int, original int) {
image[sr][sc] = color
if sr > 0 && image[sr-1][sc] == original {
fill(image, sr-1, sc, color, original)
}
if sc > 0 && image[sr][sc-1] == original {
fill(image, sr, sc-1, color, original)
}
if sc < len(image[0]) - 1 && image[sr][sc+1] == original {
fill(image, sr, sc+1, color, original)
}
if sr < len(image) - 1 && image[sr+1][sc] == original {
fill(image, sr+1, sc, color, original)
}
}
实际上比另一段代码(3毫秒)要慢(10毫秒):
func floodFill(image [][]int, sr int, sc int, color int) [][]int {
original :=image[sr][sc]
if original == color {
return image
}
var fill func( sr int, sc int )
fill = func( sr int, sc int ) {
image[sr][sc] = color
if sr > 0 && image[sr-1][sc] == original {
fill( sr-1, sc )
}
if sc > 0 && image[sr][sc-1] == original {
fill( sr, sc-1 )
}
if sc < len(image[0]) - 1 && image[sr][sc+1] == original {
fill( sr, sc+1 )
}
if sr < len(image) - 1 && image[sr+1][sc] == original {
fill( sr+1, sc )
}
}
fill( sr, sc )
return image
}
这是他们平台的一个副作用(运行第一个版本的实例稍微快一些),还是这暗示了函数变量比函数更快?
更多关于Golang中函数变量比普通函数执行更快吗?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
闭包与函数并无区别。使你的代码更快的原因是闭包参数数量的减少;实际上,你使用的是 image[][] 的本地实例,而不是在每次调用时传递它(第一种情况 + color + original)。
这是按值调用编程语言中 lambda 表达式的优势之一(如果使用得当)。
另外……不要将 LeetCode 的运行时间视为金科玉律,如果你多次运行程序,实际上总会得到不同的(有时差异很大)结果。
更多关于Golang中函数变量比普通函数执行更快吗?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,函数变量(闭包)与普通函数的性能差异通常很小,但确实存在。你观察到的现象主要源于以下几个因素:
- 闭包访问外部变量:第二个版本中,闭包
fill通过闭包引用访问image和original变量,避免了参数传递的开销。 - 参数数量减少:闭包版本只有
sr和sc两个参数,而普通函数版本有5个参数。参数传递在栈上操作,参数越多开销越大。 - 编译器优化:闭包可能被编译器更积极地内联优化。
下面是性能对比的示例代码:
package main
import (
"testing"
)
// 普通函数版本
func fillFunc(image [][]int, sr, sc, color, original int) {
// 实现同你的第一个版本
}
// 闭包版本
func fillClosure(image [][]int, sr, sc, color, original int) {
var fill func(sr, sc int)
fill = func(sr, sc int) {
// 实现同你的第二个版本
}
fill(sr, sc)
}
func BenchmarkFunc(b *testing.B) {
image := make([][]int, 100)
for i := range image {
image[i] = make([]int, 100)
}
for i := 0; i < b.N; i++ {
fillFunc(image, 50, 50, 2, 1)
}
}
func BenchmarkClosure(b *testing.B) {
image := make([][]int, 100)
for i := range image {
image[i] = make([]int, 100)
}
for i := 0; i < b.N; i++ {
fillClosure(image, 50, 50, 2, 1)
}
}
运行基准测试:
go test -bench=. -benchmem
典型结果可能显示闭包版本稍快(约5-10%),差异主要来自:
- 闭包减少了参数复制
- 闭包直接引用外部变量,减少了栈操作
- 但闭包有额外的内存分配(函数对象)
在递归深度较大时,参数减少带来的性能提升更明显。对于LeetCode这类平台,3ms和10ms的差异可能在测量误差范围内,但闭包版本确实有潜在的性能优势。

