AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
## 函数值 函数值就是闭包 ~~~ func squares() func() int { var x int return func() int { x++ return x * x } } func main() { f := squares() fmt.Println(f()) // "1" fmt.Println(f()) // "4" fmt.Println(f()) // "9" fmt.Println(f()) // "16" } ~~~ 函数值不仅仅是一串代码,还记录了状态。在squares中定义的匿名内部函数可以访问和更新squares中的局部变量,这意味着匿名函数和squares中,存在变量引用。这就是函数值属于引用类型和函数值不可比较的原因。Go使用闭包(closures)技术实现函数值,Go程序员也把函数值叫做闭包。 通过这个例子,我们看到变量的生命周期不由它的作用域决定:squares返回后,变量x仍然隐式的存在于f中。 ## 警告:捕获迭代变量 具体看go语言圣经的这一块,匿名函数对上层的局部变量,捕获的是该变量的内存地址,所以,在for每次循环中,for的返回值都是重新赋值,那么匿名变量捕获的永远是最后一次. ~~~ for i := 0; i < 10; i++ { n := i fmt.Println("i=====", &i) fmt.Println("n=====", &n) } ~~~ 结果:可以看到i的内存地址永远是同一个,而n的地址不是同一个. ``` i===== 0x1400001e318 n===== 0x1400001e320 i===== 0x1400001e318 n===== 0x1400001e330 i===== 0x1400001e318 n===== 0x1400001e338 i===== 0x1400001e318 n===== 0x1400001e340 i===== 0x1400001e318 n===== 0x1400001e348 i===== 0x1400001e318 n===== 0x1400001e350 i===== 0x1400001e318 n===== 0x1400001e358 i===== 0x1400001e318 n===== 0x1400001e360 i===== 0x1400001e318 n===== 0x1400001e368 i===== 0x1400001e318 n===== 0x1400001e370 ```