用 runtime.readmemstats 只能获取 go 程序自身内存统计,无法反映系统内存;正确做法是 linux 读 /proc/meminfo(优先 memavailable),macos 用 sysctl,windows 调 globalmemorystatusex,容器中还需读 cgroup 限制。

用 runtime.ReadMemStats 只能得到 Go 进程自己的内存,不是系统内存
很多人一搜“Go 获取内存”,立刻掉进 runtime.ReadMemStats 的坑里——它返回的是当前 Go 程序的堆分配、GC 统计等,和系统总内存、可用内存完全无关。想监控服务器资源水位、做容量预估或告警,必须绕开这个函数。
Linux 上直接读 /proc/meminfo 最可靠
Linux 是主流部署环境,/proc/meminfo 是内核暴露的权威来源,字段稳定、无依赖、零开销。Go 用 os.ReadFile 读取后解析即可,不用引入第三方库。
常见错误现象:
– 正则匹配写太宽(比如用 MemTotal.*?(\d+)),可能跨行误抓
– 忽略单位(kB 是默认单位,不是 KB 或 bytes)
– 没处理空行或注释行(虽然实际很少,但健壮代码要跳过)
实操建议:
- 用
strings.Split(string(data), "\n")按行切分,逐行strings.HasPrefix判断是否以"MemTotal:"或"MemAvailable:"开头 - 用
strconv.ParseUint(strings.Fields(line)[1], 10, 64)提取数值,再乘以 1024 得到字节数(因为单位是kB) - 优先用
MemAvailable(Linux 3.14+),它比Free + Buffers + Cached更准确反映真正可分配内存
macOS 和 Windows 需要调用系统 API,不能靠文件
macOS 没有 /proc,得用 sysctl:查 hw.memsize 得总内存;查 vm.stats.vm.v_free_count 等组合算可用内存(较复杂,推荐用现成封装)。Windows 要调 GlobalMemoryStatusEx。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
实操建议:
- 跨平台项目直接上
github.com/shirou/gopsutil/v3/mem,它内部已处理好各平台差异,API 统一返回mem.VirtualMemoryStat结构体 - 如果拒绝外部依赖,Linux 用
/proc/meminfo,macOS 用sysctl -n hw.memsize(命令行)或unix.SysctlUint64("hw.memsize")(CGO),Windows 必须写 CGO 调用GlobalMemoryStatusEx - 注意 macOS 的
v_free_count是页数,需乘以getpagesize()才是字节数;Windows 的ullAvailPhys字段才是可用物理内存
别把 MemFree 当可用内存,尤其在容器里
MemFree 在 Linux 上只表示完全未使用的内存页,现代内核会尽可能缓存文件、预读等,所以 MemFree 通常很小。真正能被新进程立即用上的,是 MemAvailable(内核 3.14+)或旧版估算值(MemFree + Buffers + Cached - Shmem)。
容器场景更危险:
– 如果在 Docker/K8s 里跑,cgroup 限制了内存上限,/proc/meminfo 仍显示宿主机总量
– 正确做法是读 /sys/fs/cgroup/memory/memory.limit_in_bytes(cgroup v1)或 /sys/fs/cgroup/memory.max(v2),再配合 memory.usage_in_bytes 算剩余
所以判断“还能不能多起一个服务”,不能只看 MemAvailable,得结合 cgroup 限制、进程 RSS、以及内核是否开启 swappiness(影响回收倾向)。
事情说清了就结束
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










