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)
}

参考资料

posted @   HachikoT  阅读(161)  评论(0编辑  收藏  举报
编辑推荐:
· 从 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)
点击右上角即可分享
微信分享提示