Go语言包级变量存储的指针在使用前是否会被GC回收?
结论
不会,Go垃圾回收器不会回收你的配置对象,gConf指针也永远不会指向无效内存地址。
核心原因
Go GC判断对象可回收的唯一标准是不存在从GC根对象出发可达该对象的引用路径,你的场景完全不满足回收条件:
- 包级全局变量
gConf属于GC标记阶段的根对象集合,程序运行期间只要对应包处于已加载状态(Go运行时正常不会卸载已加载的业务包),gConf的引用就会被GC全程追踪。 - 你在
init()方法中调用_ = utils.GetConf()时,函数执行逻辑已经把初始化完成的Conf实例地址赋值给了全局变量gConf,哪怕你没有接收这次调用的返回值,全局变量对配置实例的强引用已经生成,该实例始终处于存活状态,不可能被GC回收。
实现优化建议
你当前的单例实现和GC风险无关,但存在并发竞态隐患:如果多个goroutine首次同时调用GetConf(),可能出现重复判断gConf == nil、重复执行配置解析的问题。生产环境建议用sync.Once改造保证并发安全,改造后代码如下:
import ( "sync" env "github.com/Netflix/go-env" ) type Conf struct { DBName string `env:"MONGO_INITDB_DATABASE,required=true"` Hostname string `env:"HOSTNAME,required=true"` DBUsername string `env:"MONGO_INITDB_ROOT_USERNAME,required=true"` DBPassword string `env:"MONGO_INITDB_ROOT_PASSWORD,required=true"` } var ( gConf *Conf confOnce sync.Once ) func GetConf() *Conf { confOnce.Do(func() { gConf = new(Conf) _, err := env.UnmarshalFromEnviron(gConf) if err != nil { panic(err) } }) return gConf }
内容的提问来源于stack exchange,提问作者jacob
相关产品推荐
相关产品推荐

