最稳妥方案是直接使用gopsutil:它跨平台封装linux/macos/windows底层调用,cpu需两次采样取差值获取瞬时率,内存应基于available字段计算真实可用率,避免误用usedpercent或单位错误。

用 gopsutil 获取 CPU 和内存使用率最稳妥
Go 标准库不直接暴露系统资源指标,硬写 /proc 解析或调用 syscall 容易跨平台出错、版本兼容性差。实际项目里,gopsutil 是事实标准——它封装了 Linux / macOS / Windows 底层差异,API 稳定,且支持按核/全局、实时/平均等粒度。
安装:
go get github.com/shirou/gopsutil/v3/cpu<br>go get github.com/shirou/gopsutil/v3/mem
-
CPU.Percent默认返回最近 0.5 秒的使用率,传0表示阻塞等待一次采样(适合单次监控);传1会返回过去 1 秒的平均值,但需两次调用才能算出(第一次初始化,第二次才有效) -
mem.VirtualMemory返回的是*mem.VirtualMemoryStat,其中Percent是 float64 类型,直接可用;Total和Used单位是字节,别误当 MB 用 - Windows 下若权限不足,
CPU.Percent可能返回空切片或nil,建议加len() > 0判空
避免 CPU.Percent 返回空切片或卡死
常见错误是直接调用 cpu.Percent(0, false) 期望立刻拿到一个数字,结果返回 []float64{} 或长时间无响应——这是因为某些系统(尤其是 Windows 或容器环境)需要先触发一次采样周期。
- 安全做法:先调用一次
cpu.Percent(1, false)初始化(忽略返回值),再隔 1 秒调用cpu.Percent(0, false)获取真实值 - 更轻量方案:用
cpu.Times(false)获取各核时间戳,自己算差值,但要注意CPUUsage字段在不同系统含义不同(Linux 是总时间,Windows 是归一化百分比) - 容器内运行时,
/proc/stat可能被 cgroup 限制,gopsutil会 fallback 到cgroup解析,此时CPU.Percent返回的是容器限额内的占比,不是宿主机全局值
内存统计要区分 Used 和 Available
mem.VirtualMemory 的 Used 包含 cache/buffer,而用户真正关心的是“还有多少内存可分配”,应该看 Available 字段。Linux 下这个值来自 /proc/meminfo 的 MemAvailable,但老内核(gopsutil 会退化为 Free + Buffers + Cached 估算——误差可能达几百 MB。
- 检查是否支持:
cat /proc/meminfo | grep MemAvailable,没这行就说明内核太旧 - 如果必须支持旧内核,建议同时采集
Free和Buffers,按公式Free + Buffers + Cached - SReclaimable手动估算(SReclaimable是 slab 中可回收部分) -
Percent字段是基于Total - Available计算的,所以旧内核下该值偏高,别直接当告警阈值用
单次函数封装要注意超时和错误传播
把 CPU 和内存读取塞进一个函数里,最容易忽略的是任一子调用失败导致整个监控失效。比如 cpu.Percent 在 Docker Desktop for Mac 上偶尔 panic,或 mem.VirtualMemory 因权限问题返回 error。
- 不要用
panic处理采集失败,统一返回(float64, float64, error)三元组,让上层决定是重试还是跳过 - 给每个子调用加 context.WithTimeout,例如 2 秒——
gopsutil某些路径(如 WMI 查询)在 Windows 上可能卡住 - 避免并发调用
cpu.Percent和mem.VirtualMemory:它们内部都可能打开 /proc 文件,高频调用时文件描述符可能耗尽
真正难的不是读数据,而是理解每个数字背后的真实约束条件:CPU 百分比是相对谁算的,内存 Available 在哪些场景下不准,以及你的监控目标到底是“系统负载”还是“应用可用资源”。这些细节不厘清,数值再准也没用。











