You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中实现获取系统内存、磁盘、CPU指标的函数

实现系统资源使用率监控(无第三方库)

针对Linux系统(你的CPU监控代码依赖/proc/stat,属于Linux特有的虚拟文件系统),以下是无需第三方库的内存、磁盘使用率实现,同时优化了你的CPU监控代码的错误处理:

1. 内存使用率监控

读取/proc/meminfo文件,解析MemTotal和MemAvailable字段(MemAvailable是系统估算的可立即分配给新进程的内存,比MemFree更准确),计算使用率:

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func getMemUsage() (float64, error) {
    file, err := os.Open("/proc/meminfo")
    if err != nil {
        return 0, err
    }
    defer file.Close()

    var total, available uint64
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()
        fields := strings.Fields(line)
        if len(fields) < 2 {
            continue
        }
        switch fields[0] {
        case "MemTotal:":
            val, err := strconv.ParseUint(fields[1], 10, 64)
            if err != nil {
                return 0, fmt.Errorf("parse MemTotal failed: %w", err)
            }
            total = val
        case "MemAvailable:":
            val, err := strconv.ParseUint(fields[1], 10, 64)
            if err != nil {
                return 0, fmt.Errorf("parse MemAvailable failed: %w", err)
            }
            available = val
        }
    }

    if err := scanner.Err(); err != nil {
        return 0, err
    }

    if total == 0 {
        return 0, fmt.Errorf("invalid total memory value")
    }

    usage := 100 * float64(total-available) / float64(total)
    return usage, nil
}

2. 磁盘使用率监控

使用syscall.Statfs获取指定挂载点的磁盘空间信息,计算使用率:

import "syscall"

func getDiskUsage(mountPoint string) (float64, error) {
    var stat syscall.Statfs_t
    if err := syscall.Statfs(mountPoint, &stat); err != nil {
        return 0, err
    }

    // 总空间:块数 * 块大小
    total := uint64(stat.Blocks) * uint64(stat.Bsize)
    // 可用空间:普通用户可使用的块数 * 块大小(Bavail比Bfree更符合实际场景)
    available := uint64(stat.Bavail) * uint64(stat.Bsize)

    if total == 0 {
        return 0, fmt.Errorf("invalid total disk space")
    }

    usage := 100 * float64(total-available) / float64(total)
    return usage, nil
}

3. 优化后的CPU监控代码

修复了原代码的错误处理逻辑(返回错误而非直接打印),替换了已废弃的ioutil.ReadFile为os.ReadFile:

import (
    "fmt"
    "os"
    "strconv"
    "strings"
    "time"
)

func getCPUTrack() (idle, total uint64, err error) {
    contents, err := os.ReadFile("/proc/stat")
    if err != nil {
        return 0, 0, err
    }

    lines := strings.Split(string(contents), "\n")
    for _, line := range lines {
        fields := strings.Fields(line)
        if len(fields) == 0 {
            continue
        }
        if fields[0] == "cpu" {
            if len(fields) < 5 {
                return 0, 0, fmt.Errorf("invalid cpu stat line format")
            }
            for i := 1; i < len(fields); i++ {
                val, parseErr := strconv.ParseUint(fields[i], 10, 64)
                if parseErr != nil {
                    return 0, 0, fmt.Errorf("parse cpu stat field %d failed: %w", i, parseErr)
                }
                total += val
                if i == 4 {
                    idle = val
                }
            }
            return idle, total, nil
        }
    }

    return 0, 0, fmt.Errorf("cpu stat line not found")
}

func getCPUUsage() (float64, error) {
    idle0, total0, err := getCPUTrack()
    if err != nil {
        return 0, err
    }

    time.Sleep(3 * time.Second)

    idle1, total1, err := getCPUTrack()
    if err != nil {
        return 0, err
    }

    idleTicks := float64(idle1 - idle0)
    totalTicks := float64(total1 - total0)

    if totalTicks == 0 {
        return 0, fmt.Errorf("total cpu ticks unchanged")
    }

    cpuUsage := 100 * (totalTicks - idleTicks) / totalTicks
    return cpuUsage, nil
}

示例使用

func main() {
    // 获取内存使用率
    memUsage, err := getMemUsage()
    if err != nil {
        fmt.Printf("Failed to get memory usage: %v\n", err)
        return
    }
    fmt.Printf("Memory usage: %.2f%%\n", memUsage)

    // 获取根目录磁盘使用率
    diskUsage, err := getDiskUsage("/")
    if err != nil {
        fmt.Printf("Failed to get disk usage: %v\n", err)
        return
    }
    fmt.Printf("Disk usage (/): %.2f%%\n", diskUsage)

    // 获取CPU使用率
    cpuUsage, err := getCPUUsage()
    if err != nil {
        fmt.Printf("Failed to get CPU usage: %v\n", err)
        return
    }
    fmt.Printf("CPU usage: %.2f%%\n", cpuUsage)
}

注意事项

  • 以上代码仅适用于Linux系统,依赖/proc虚拟文件系统和Linux专属的syscall.Statfs实现。
  • 磁盘监控需传入正确的挂载点(如/home、/var等)。
  • CPU监控需要等待3秒获取两次采样值,实际使用中可根据需求调整等待时长。

内容的提问来源于stack exchange,提问作者Anna P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:24:52