go结构体持有外部资源时需显式释放,gc不自动清理c指针、数据库连接等;gocql.session须调用close()并复用;c结构体优先复制到go内存;channel关闭仅为通信信号,须由最后写入者关闭,避免泄漏。

Go 没有析构函数,对象生命周期结束 ≠ 资源自动释放。结构体里存了 *gocql.Session、*C.struct_foo 或未关闭的 net.Conn,不显式清理就会泄漏。
struct 里持有外部资源时,必须自己管好 Close/Free
Go 的 struct 不会自动触发清理逻辑,哪怕它被 GC 回收了,里面的 C 指针、数据库连接、文件句柄也不会跟着消失。
-
gocql.Session必须调用s.Close(),且推荐复用而非每请求新建;滥用defer s.Close()在 long-lived struct 里等于没关 - C 指针如
*C.b,不能只靠runtime.SetFinalizer—— 它不保证执行时机,也不保证执行次数;必须提供显式的Free()方法并由调用方主动调用 - 若 C 结构体简单(比如只有几个字段),优先复制内容到 Go 内存:
s C.b而非s *C.b,让 GC 自动兜底
channel 关闭不是资源释放开关,而是通信语义信号
关闭 channel 只表示“不再发数据”,不代表接收端自动退出或 goroutine 被回收。乱关、早关、多写入者竞相关,都会引发 panic 或 goroutine 泄漏。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 仅由最后一个潜在写入 goroutine 调用
close(ch);worker 只读,绝不关 - 依赖
for range ch退出前,必须确保所有写入已结束 —— 常用sync.WaitGroup等写入 goroutine 退出后再 close - 事件流、日志通道这类「可能永远不关闭」的场景,别用
range,改用for { select { case
短生命周期对象要重置,别等 GC 扫描
频繁创建 map/slice 但只用一次?GC 来回收太慢,内存峰值会虚高。Go 1.21+ 提供了更轻量的清理方式。
- map 清空用
m = map[K]V{}或clear(m)(Go 1.21+),避免重建开销 - slice 重用时设
s = s[:0],保留底层数组,下次 append 可复用 - 不要靠
runtime.GC()强制回收 —— 它是提示,不是指令,且代价高
最易被忽略的一点:资源释放责任必须落在调用方,而不是封装 struct 的内部。哪怕你写了 Close() 方法,如果没人调,它就永远不会运行 —— 这不是语言缺陷,是 Go 显式优于隐式的体现。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










