go闭包

知道js闭包的肯定能非常快速的了解go的闭包,非常类似

闭包的概念:是在其语法上下文中引用了自由变量的函数(太官方)

先解释下作用域:每个变量都有自己的作用域,如果找不到需要的变量则会继续向上查,直到找到为止,遇到的问题就是内部的能访问外包的变量,但是外层无法访问内层的变量,如何能实现外层访问内层的变量,则就是闭包。

package main

import (
	"fmt"
)

func main() {
	f := test(20)
	f()
}

func test(x int) func() {
	fmt.Println(x)

	return func() {
		fmt.Println(x)
	}
}

 实现原理:闭包引用了原环境变量的指针(可以不理解)

### Go语言闭包的概念 闭包是一种特殊的函数形式,在许多现代编程语言中都有支持,包括Go语言。它允许函数不仅携带自身的逻辑代码,还可以捕获并保存在其定义环境中存在的变量状态[^1]。具体而言,当一个匿名函数或者常规函数能够访问其所在作用域之外的局部变量时,该结构即构成闭包。 #### 闭包的特点 - **自由变量绑定**:闭包通过引用的方式绑定了外部作用域中的变量,即使这些变量原本应该随着作用域结束而销毁,但由于闭包的存在,它们会被继续保留于内存之中直到不再被任何地方所引用为止[^2]。 - **动态生命周期管理**:从运行机制角度来看,当创建了一个闭包实例之后,那些被捕获进去的变量将会被放置到堆区而非栈区内存当中去处理;因此即便原生调用者退出了自己的执行上下文环境,只要还有现存的有效闭包持有对于某个特定变量的引用关系,则此变量就不会遭到垃圾回收器清理掉[^4]。 ### 实际应用案例分析 下面给出一段具体的程序来展示如何利用Go语言特性构建简单的计数器功能: ```go package main import "fmt" func counter() func() int { var count int // 定义一个局部变量count用于记录次数 return func() int { // 返回一个匿名函数作为闭包的一部分 count += 1 // 修改外部作用域内的变量值 return count // 将当前累计的结果返回给外界使用者查看 } } func main(){ c := counter() fmt.Println(c()) // 输出: 1 fmt.Println(c()) // 输出: 2 fmt.Println(c()) // 输出: 3 } ``` 在这个例子里面可以看到我们先声明了一个`counter()`工厂方法用来生产新的独立个体化的计数值追踪工具——每当调用一次由前者产出的新鲜版本闭包对象c的时候都会使得内部私有的静态成员属性count增加一单位数量级,并且同步反馈最新的统计总数出来供观察使用[^3]。 另外需要注意的是关于共享可变状态方面的一个常见陷阱示例如下所示: ```go package main import ( "fmt" ) func main() { for i := 0; i < 5; i++ { go func() { fmt.Println(i) // 此处打印出来的i可能并非预期中的顺序值 }() } time.Sleep(1e9) // 防止主线程提前终止导致goroutine未完成工作前就被摧毁 } ``` 这里由于所有的协程都共同操作着同一个迭代索引变量i的缘故,所以最终呈现的效果很可能是五个完全相同的数字(取决于实际调度情况)。为了避免这种情况发生我们可以采取立即执行表达式的手段即时固定住每次循环当时的参数副本从而达到目的效果如下调整后的写法即可解决上述问题[^5]: ```go for _, v := range []int{0, 1, 2, 3, 4} { go func(v int){ fmt.Println(v) }(v) } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值