Get top CPU info in Go
17:08 04 Jun 2026

I'm trying to get *nix top's CPU info in Go, and found github.com/shirou/gopsutil. I.e.,

I'm using shirou/gopsutil/v4/process API to get CPU info as close to top as possible. However, this is what I observed from my program:

I'm calling process.CPUPercent(), and my debug logs seems that CPUPercent() returns the total CPU percentage (fraction of all cores combined), whereas top shows the per‑core CPU percentage (a single core = 100 %) --

I ran the program and captured the debug logs which show that the CPU percentages reported by CPUPercent() are very low for some PIDs that top reports as high. Specifically, top says PID 2176 is at 27.5% CPU (in one snapshot) but the debug log shows cpu=2.96% consistently. PID 2119 top shows 8.6% but debug shows 1.91%. PID 2462 top shows 7.6% but debug shows 3.87%. PID 38488 top shows 50% and debug shows 43.40%, which is the only close one. That seems the CPUPercent() values are not per-core percentages but rather percentages of total available CPU (sum of all cores). Typically, top shows the percentage of a single CPU core, i.e., if a process uses 100% of one core on a multi-core system, top shows 100%. But gopsutil's CPUPercent() returns the percentage of total CPU time across all cores.

So I wrote a simplest code to verify the above, enclosed below.

The result, when monitoring process PID: 2176, which top constantly showing a CPU% of 3.3, I'm having the following:

📊 Monitoring process: chrome [PID: 2176]
--------------------------------------------------
[12:59:07.523] gopsutil raw:   0.00%  |  top-style:   0.00%
[12:59:08.625] gopsutil raw:   0.00%  |  top-style:   0.00%
[12:59:09.725] gopsutil raw:   9.95%  |  top-style:  79.58%
[12:59:10.827] gopsutil raw:   0.00%  |  top-style:   0.00%
[12:59:11.929] gopsutil raw:   9.91%  |  top-style:  79.27%
[12:59:13.030] gopsutil raw:   0.00%  |  top-style:   0.00%
[12:59:14.131] gopsutil raw:   0.00%  |  top-style:   0.00%
[12:59:15.232] gopsutil raw:   0.00%  |  top-style:   0.00%
[12:59:16.333] gopsutil raw:   0.00%  |  top-style:   0.00%
[12:59:17.435] gopsutil raw:   0.00%  |  top-style:   0.00%

I.e., using the first % column, if I ignore all 0.00% values, then the CPU% would be high; yet if I use them all, then the CPU% (~2%) would be much lower than the 3.3%.

So, all in all, somebody please provide a simplest code which uses shirou/gopsutil/v4/process API to get CPU info, and the reading can be as close to top as possible.

Thanks

package main

import (
    "fmt"
    "os"
    "runtime"
    "strconv"
    "time"

    "github.com/shirou/gopsutil/v4/process"
)

func main() {
    // Get number of logical CPU cores
    numCores := float64(runtime.NumCPU())
    fmt.Printf("🔹 System has %.0f logical cores (top style: 100%% = one core fully used)\n\n", numCores)

    // Read PID from command line argument
    if len(os.Args) < 2 {
        fmt.Println("Usage: go run main.go ")
        fmt.Println("Example: go run main.go 1234")
        return
    }
    pid, err := strconv.ParseInt(os.Args[1], 10, 32)
    if err != nil {
        fmt.Printf("Invalid PID: %v\n", err)
        return
    }
    targetPID := int32(pid)

    // Create process object
    p, err := process.NewProcess(targetPID)
    if err != nil {
        fmt.Printf("Failed to open process with PID %d: %v\n", targetPID, err)
        return
    }

    name, _ := p.Name()
    fmt.Printf("📊 Monitoring process: %s [PID: %d]\n", name, targetPID)
    fmt.Println("--------------------------------------------------")

    // Collect 10 samples
    for i := 0; i < 10; i++ {
        // Percent() measures CPU usage over the given interval (here 100ms)
        // This gives a value that represents total usage across all cores
        totalPercent, err := p.Percent(100 * time.Millisecond)
        if err != nil {
            fmt.Printf("Error reading CPU: %v\n", err)
            break
        }

        // Convert to top style: 100% means one full core
        topStylePercent := totalPercent * numCores

        fmt.Printf("[%s] gopsutil raw: %6.2f%%  |  top-style: %6.2f%%\n",
            time.Now().Format("15:04:05.000"), totalPercent, topStylePercent)

        time.Sleep(1 * time.Second)
    }
}

PS. none-zero case:

when monitoring process PID: 2518, which top constantly showing a CPU% of 60, I'm having:

📊 Monitoring process: chrome [PID: 2518]
--------------------------------------------------
[13:06:16.007] gopsutil raw:  29.69%  |  top-style: 237.52%
[13:06:17.109] gopsutil raw:  59.60%  |  top-style: 476.82%
[13:06:18.211] gopsutil raw:  39.80%  |  top-style: 318.42%
[13:06:19.312] gopsutil raw:  49.68%  |  top-style: 397.47%
[13:06:20.414] gopsutil raw:  49.70%  |  top-style: 397.56%
[13:06:21.516] gopsutil raw:  49.71%  |  top-style: 397.67%
[13:06:22.617] gopsutil raw:  39.76%  |  top-style: 318.11%
[13:06:23.718] gopsutil raw:  49.63%  |  top-style: 397.08%
[13:06:24.819] gopsutil raw:  49.67%  |  top-style: 397.36%
[13:06:25.920] gopsutil raw:  49.66%  |  top-style: 397.31%

all reading execpt one are much lower than 60%.

go monitoring cpu-usage