MST

星途 面试题库

面试题:Go语言匿名函数与闭包的内存管理

假设你有如下代码片段: ```go package main import ( "fmt" ) func outer() func() int { num := 10 return func() int { num++ return num } } ``` 请解释在多次调用`outer()`返回的匿名函数时,内存是如何管理的,为什么`num`的值能在多次调用中保持状态,并且可能会存在什么潜在的内存问题。
48.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 内存管理
    • outer函数被调用时,会在栈上为其分配局部变量num
    • 但是,当outer函数返回匿名函数时,由于匿名函数引用了numnum不能随着outer函数调用结束而被销毁。Go语言的垃圾回收器(GC)会识别这种引用关系,将num所在的内存块移动到堆上。
    • 每次调用匿名函数时,都是在堆上操作这个num变量。
  2. 保持状态的原因
    • 匿名函数形成了闭包。闭包是一个函数和与其相关的引用环境组合而成的实体。在这里,匿名函数引用了outer函数中的num变量,即使outer函数执行完毕,由于闭包的存在,num的状态依然被保存。
    • 每次调用匿名函数时,都是对同一个堆上的num变量进行操作,所以num的值能在多次调用中保持状态。
  3. 潜在的内存问题
    • 内存泄漏:如果匿名函数被长期持有(例如,被存储在全局变量中且不会被释放),而num占用的内存空间不断增大(例如,如果num是一个不断增长的复杂数据结构,而不是简单的int),那么这部分内存就不能被垃圾回收器回收,从而导致内存泄漏。
    • 并发问题:如果多个协程同时调用这个匿名函数,由于num的操作不是原子的,可能会出现竞态条件(race condition),导致num的值出现错误。例如,在并发环境下,两个协程同时读取num的值,然后分别加1,再写回,最终num只增加了1而不是2。这种情况下,需要使用同步机制(如互斥锁sync.Mutex)来保护对num的操作。