go闭包
go闭包
在go语言中,函数是“一等公民”,所谓“一等公民”是指函数可以作为类型,函数对象可以像普通对象那样用来赋值,作为参数传递,作为返回值返回。
而go的闭包则是函数的高阶应用,所谓闭包是指引用了自由变量的匿名函数,被引用的自由变量和匿名函数对象一同存在,即使已经离开了自由变量的环境也不会被释放或者删除,在闭包中可以继续使用这个自由变量。
匿名函数 + 自用变量引用 = 闭包
举例:
package main
import "fmt"
func getSequence() func() int {
i := 0
return func() int {
i += 1
return i
}
}
func main() {
nextNumber1 := getSequence()
fmt.Println(nextNumber1()) // 1
fmt.Println(nextNumber1()) // 2
fmt.Println(nextNumber1()) // 3
// 下面又重新从1开始计数,是因为重新调用了getSequence函数,此时返回的闭包函数引用的局部变量是一个新的变量
nextNumber2 := getSequence()
fmt.Println(nextNumber2()) // 1
fmt.Println(nextNumber2()) // 2
}
go闭包遇到循环
package main
import (
"fmt"
"time"
)
func main() {
s := []string{"a", "b", "c"}
for _, v := range s {
go func() {
fmt.Println(v)
}()
}
time.Sleep(time.Second * 1)
}
当循环中需要捕获自由变量的时候,常常会因为捕获到的是同一个变量,导致得不到预期结果(预期是每个闭包引用的是本次循环得到的值)。
- 方案一:重新定义一个局部变量
package main
import (
"fmt"
"time"
)
func main() {
s := []string{"a", "b", "c"}
for _, v := range s {
v := v
go func() {
fmt.Println(v)
}()
}
time.Sleep(time.Second * 1)
}
- 方案二:作为参数传进去,不过这样就没有自由变量了
package main
import (
"fmt"
"time"
)
func main() {
s := []string{"a", "b", "c"}
for _, v := range s {
go func(v string) {
fmt.Println(v)
}(v)
}
time.Sleep(time.Second * 1)
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)