别用 runtime.ReadMemStats() 查服务器内存,它只反映 Go 进程堆内存;查系统内存应读 /proc/meminfo(Linux)、sysctl hw.memsize(macOS)、GlobalMemoryStatusEx(Windows),或直接用 gopsutil。

别用 runtime.ReadMemStats() 查服务器内存——它只告诉你 Go 进程自己花了多少堆内存,和系统总内存、可用内存、使用率完全无关。
Linux 上直接读 /proc/meminfo 最可靠
这是内核暴露的权威来源,无依赖、零开销、字段稳定。关键不是“能不能读”,而是怎么解析才不出错:
- 逐行扫描,用
strings.HasPrefix(line, "MemTotal:")和strings.HasPrefix(line, "MemAvailable:")匹配,别用跨行正则 -
MemAvailable:优先于MemFree:(Linux 3.14+),它已扣除不可回收缓存,更接近真实可分配量 - 单位是 kB,不是 KB 或 bytes;提取数值后必须乘以
1024才是字节数 - 跳过空行、注释行(虽然少见,但健壮代码要处理)
容器里 MemAvailable 仍是宿主机值
你在 Kubernetes Pod 里跑这段代码,/proc/meminfo 返回的还是节点总内存和总可用内存,不是你这个容器能用的上限。真要查容器内存限制,得看 cgroup:
- cgroup v2:
/sys/fs/cgroup/memory.max(值为max表示无限制,否则是字节数) - cgroup v1:
/sys/fs/cgroup/memory/memory.limit_in_bytes - 容器实际已用内存(含 page cache):
/sys/fs/cgroup/memory/memory.usage_in_bytes
注意:这些路径需要容器有相应权限挂载,且默认可能被隐藏;若不可读,/proc/meminfo 就只能当参考,不能用于容量决策。
立即学习“go语言免费学习笔记(深入)”;
跨平台别硬写三套逻辑
macOS 没 /proc,得调 sysctl hw.memsize;Windows 必须用 CGO 调 GlobalMemoryStatusEx。手动适配容易漏掉权限、字段变更、页大小换算等细节。生产环境建议直接用:
github.com/shirou/gopsutil/v3/mem.VirtualMemory() —— 它内部已封装好各平台差异,返回统一结构体,含 Total、Available、UsedPercent 字段。Windows 下需启用 CGO_ENABLED=1,macOS 不依赖命令行工具。
runtime.ReadMemStats() 的真实用途
它只适合监控 Go 进程自身内存行为,比如:
-
m.Alloc突增?说明新分配对象没及时释放 -
m.NumGC飙高 +m.PauseNs增长?GC 压力大,可能需调优 GOGC 或检查内存泄漏 -
m.Sys持续上涨?Go 向 OS 申请的虚拟内存不断扩张,可能是sync.Pool持久化、大 slice 预分配未收缩,或 CGO 分配未归还
但它永远不反映系统水位。把 m.Sys 当服务器总内存用,等于拿体温计去量气压——单位都对不上。


















