不能。Go 的 runtime 包仅提供进程级运行时信息,如逻辑 CPU 数(runtime.NumCPU)和堆内存快照(runtime.ReadMemStats),无法获取系统级 CPU 占用率或内存使用百分比,因其不读取 /proc/stat、/proc/meminfo 或调用系统接口;准确监控需用 gopsutil/v3 等第三方库或直接解析系统文件。

用 runtime 能否准确获取系统级 CPU 和内存占用率?
不能。Go 的 runtime 包只暴露进程自身运行时信息,比如 runtime.NumCPU() 返回逻辑 CPU 数量,runtime.ReadMemStats() 返回当前 Go 进程的堆/栈内存统计,但这些和「系统整体 CPU 占用率」「系统总内存使用百分比」完全无关——它不读取 /proc/stat 或 /proc/meminfo,也不调用系统命令。
常见误用是把 MemStats.Alloc 除以 MemStats.Sys 当作“内存占用率”,这实际只是 Go 进程内已分配内存占其向 OS 申请总量的比例,和系统剩余内存毫无关系。
为什么推荐 shirou/gopsutil 而不是自己解析 /proc?
Linux 下读取 /proc/stat 算 CPU 使用率需要至少两次采样、做差值、再归一化;/proc/meminfo 中的 MemAvailable 字段需兼容老内核(
shirou/gopsutil 封装了这些逻辑,并跨平台支持(Linux/macOS/Windows),且默认启用缓存避免高频调用开销:
-
cpu.Percent(0, false)返回 float64 切片,0表示全核聚合,false表示非阻塞(即立即返回上次采样结果) -
mem.VirtualMemory()返回*mem.VirtualMemoryStat,其中Percent字段就是系统内存占用率(基于MemAvailable计算) - 首次调用
cpu.Percent会触发初始化采样,第二次才返回有效值;若需精确间隔,应配合time.Sleep控制周期
如何避免 gopsutil 的常见卡顿和权限问题?
在容器或受限环境里,gopsutil 默认尝试读取 /proc 下多个文件,若权限不足或路径被屏蔽(如 Docker 默认不挂载 /proc/sys),可能阻塞数秒甚至 panic。
实操建议:
- 启动时加
-v参数运行程序,观察是否输出failed to get process info: permission denied类日志 - 容器中务必挂载
/proc:启动命令加--volume /proc:/proc:ro - 若只需系统级指标(不要进程列表),可禁用进程探测:
gopsutil.WithPID(false)(需 v3.22.0+) - CPU 采样频率别设太高——
cpu.Percent(100*time.Millisecond, false)在某些低配机器上反而因频繁系统调用导致 CPU 毛刺
一个轻量、可直接复用的监控函数示例
以下函数每秒打印一次系统 CPU 和内存使用率,已规避首次采样空值、并发竞争、错误忽略等问题:
func monitorSystem() {
var lastPercent float64
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
cpuPercents, err := cpu.Percent(0, false)
if err != nil {
log.Printf("cpu.Percent error: %v", err)
continue
}
if len(cpuPercents) == 0 {
continue
}
cpu := cpuPercents[0]
<pre class="brush:php;toolbar:false;"> mem, err := mem.VirtualMemory()
if err != nil {
log.Printf("mem.VirtualMemory error: %v", err)
continue
}
// 避免首次调用返回 0(未完成初始化)
if cpu == 0 && lastPercent == 0 {
lastPercent = cpu
continue
}
lastPercent = cpu
log.Printf("CPU: %.1f%%, Mem: %.1f%%", cpu, mem.Percent)
}}
注意:cpu.Percent 返回的是自上次调用以来的平均占用率,不是瞬时值;mem.Percent 是当前可用内存占比的反向值(即 100 - 可用%),这个定义和 top 命令一致,但容易误解为“已用百分比”——其实它就是已用率。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











