Skip to main content
Learn how to create a basic system monitoring tool using gopsutil. This example demonstrates the fundamental packages for monitoring CPU, memory, and disk resources.

What You’ll Build

A command-line tool that displays:
  • CPU usage percentage and core count
  • Memory usage statistics (total, used, available)
  • Disk usage for mounted partitions
  • System uptime and host information

Prerequisites

1

Install gopsutil

go get github.com/shirou/gopsutil/v4
2

Create your project

mkdir system-monitor
cd system-monitor
go mod init system-monitor

Building the Monitor

1

Import required packages

Create a main.go file and import the necessary packages:
main.go
package main

import (
    "fmt"
    "time"

    "github.com/shirou/gopsutil/v4/cpu"
    "github.com/shirou/gopsutil/v4/disk"
    "github.com/shirou/gopsutil/v4/host"
    "github.com/shirou/gopsutil/v4/mem"
)
2

Create CPU monitoring function

Add a function to display CPU information:
main.go
func displayCPUInfo() error {
    // Get CPU usage percentage
    percentages, err := cpu.Percent(time.Second, false)
    if err != nil {
        return fmt.Errorf("error getting CPU percent: %w", err)
    }

    // Get number of CPU cores
    cores, err := cpu.Counts(true)
    if err != nil {
        return fmt.Errorf("error getting CPU counts: %w", err)
    }

    fmt.Println("\n=== CPU Information ===")
    fmt.Printf("CPU Usage: %.2f%%\n", percentages[0])
    fmt.Printf("CPU Cores: %d\n", cores)

    return nil
}
The cpu.Percent() function takes an interval duration and a boolean flag. Set percpu to false for overall usage, or true for per-core usage.
3

Create memory monitoring function

Add a function to display memory statistics:
main.go
func displayMemoryInfo() error {
    // Get virtual memory statistics
    vmStat, err := mem.VirtualMemory()
    if err != nil {
        return fmt.Errorf("error getting memory info: %w", err)
    }

    // Get swap memory statistics
    swapStat, err := mem.SwapMemory()
    if err != nil {
        return fmt.Errorf("error getting swap info: %w", err)
    }

    fmt.Println("\n=== Memory Information ===")
    fmt.Printf("Total: %v MB\n", vmStat.Total/1024/1024)
    fmt.Printf("Used: %v MB (%.2f%%)\n", 
        vmStat.Used/1024/1024, vmStat.UsedPercent)
    fmt.Printf("Available: %v MB\n", vmStat.Available/1024/1024)
    fmt.Printf("\nSwap Total: %v MB\n", swapStat.Total/1024/1024)
    fmt.Printf("Swap Used: %v MB (%.2f%%)\n", 
        swapStat.Used/1024/1024, swapStat.UsedPercent)

    return nil
}
Memory values are returned in bytes. Divide by 1024/1024 to convert to MB, or 1024/1024/1024 for GB.
4

Create disk monitoring function

Add a function to display disk usage:
main.go
func displayDiskInfo() error {
    // Get all partitions
    partitions, err := disk.Partitions(false)
    if err != nil {
        return fmt.Errorf("error getting partitions: %w", err)
    }

    fmt.Println("\n=== Disk Information ===")
    for _, partition := range partitions {
        // Get usage statistics for each partition
        usageStat, err := disk.Usage(partition.Mountpoint)
        if err != nil {
            continue // Skip partitions we can't access
        }

        fmt.Printf("\nDevice: %s\n", partition.Device)
        fmt.Printf("Mountpoint: %s\n", partition.Mountpoint)
        fmt.Printf("Filesystem: %s\n", partition.Fstype)
        fmt.Printf("Total: %v GB\n", usageStat.Total/1024/1024/1024)
        fmt.Printf("Used: %v GB (%.2f%%)\n", 
            usageStat.Used/1024/1024/1024, usageStat.UsedPercent)
        fmt.Printf("Free: %v GB\n", usageStat.Free/1024/1024/1024)
    }

    return nil
}
Always use the Mountpoint field (not Device) when calling disk.Usage(). The function expects a filesystem path like / or /home, not a device path like /dev/sda1.
5

Add host information function

Add a function to display system information:
main.go
func displayHostInfo() error {
    // Get host information
    hostInfo, err := host.Info()
    if err != nil {
        return fmt.Errorf("error getting host info: %w", err)
    }

    // Get uptime
    uptime, err := host.Uptime()
    if err != nil {
        return fmt.Errorf("error getting uptime: %w", err)
    }

    fmt.Println("\n=== Host Information ===")
    fmt.Printf("Hostname: %s\n", hostInfo.Hostname)
    fmt.Printf("OS: %s\n", hostInfo.OS)
    fmt.Printf("Platform: %s\n", hostInfo.Platform)
    fmt.Printf("Platform Version: %s\n", hostInfo.PlatformVersion)
    fmt.Printf("Kernel Version: %s\n", hostInfo.KernelVersion)
    fmt.Printf("Uptime: %v hours\n", uptime/3600)

    return nil
}
6

Create the main function

Bring it all together in the main function:
main.go
func main() {
    fmt.Println("System Monitor")
    fmt.Println("==============")

    // Display all system information
    if err := displayHostInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    if err := displayCPUInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    if err := displayMemoryInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    if err := displayDiskInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}
7

Run your monitor

Build and run the program:
go run main.go
You should see output similar to:
System Monitor
==============

=== Host Information ===
Hostname: my-computer
OS: linux
Platform: ubuntu
Platform Version: 22.04
Kernel Version: 5.15.0-76-generic
Uptime: 24 hours

=== CPU Information ===
CPU Usage: 15.32%
CPU Cores: 8

=== Memory Information ===
Total: 16384 MB
Used: 8192 MB (50.00%)
Available: 8192 MB

Swap Total: 4096 MB
Swap Used: 0 MB (0.00%)

=== Disk Information ===

Device: /dev/sda1
Mountpoint: /
Filesystem: ext4
Total: 500 GB
Used: 250 GB (50.00%)
Free: 250 GB

Complete Code

Here’s the complete main.go file:
main.go
package main

import (
    "fmt"
    "time"

    "github.com/shirou/gopsutil/v4/cpu"
    "github.com/shirou/gopsutil/v4/disk"
    "github.com/shirou/gopsutil/v4/host"
    "github.com/shirou/gopsutil/v4/mem"
)

func displayHostInfo() error {
    hostInfo, err := host.Info()
    if err != nil {
        return fmt.Errorf("error getting host info: %w", err)
    }

    uptime, err := host.Uptime()
    if err != nil {
        return fmt.Errorf("error getting uptime: %w", err)
    }

    fmt.Println("\n=== Host Information ===")
    fmt.Printf("Hostname: %s\n", hostInfo.Hostname)
    fmt.Printf("OS: %s\n", hostInfo.OS)
    fmt.Printf("Platform: %s\n", hostInfo.Platform)
    fmt.Printf("Platform Version: %s\n", hostInfo.PlatformVersion)
    fmt.Printf("Kernel Version: %s\n", hostInfo.KernelVersion)
    fmt.Printf("Uptime: %v hours\n", uptime/3600)

    return nil
}

func displayCPUInfo() error {
    percentages, err := cpu.Percent(time.Second, false)
    if err != nil {
        return fmt.Errorf("error getting CPU percent: %w", err)
    }

    cores, err := cpu.Counts(true)
    if err != nil {
        return fmt.Errorf("error getting CPU counts: %w", err)
    }

    fmt.Println("\n=== CPU Information ===")
    fmt.Printf("CPU Usage: %.2f%%\n", percentages[0])
    fmt.Printf("CPU Cores: %d\n", cores)

    return nil
}

func displayMemoryInfo() error {
    vmStat, err := mem.VirtualMemory()
    if err != nil {
        return fmt.Errorf("error getting memory info: %w", err)
    }

    swapStat, err := mem.SwapMemory()
    if err != nil {
        return fmt.Errorf("error getting swap info: %w", err)
    }

    fmt.Println("\n=== Memory Information ===")
    fmt.Printf("Total: %v MB\n", vmStat.Total/1024/1024)
    fmt.Printf("Used: %v MB (%.2f%%)\n", 
        vmStat.Used/1024/1024, vmStat.UsedPercent)
    fmt.Printf("Available: %v MB\n", vmStat.Available/1024/1024)
    fmt.Printf("\nSwap Total: %v MB\n", swapStat.Total/1024/1024)
    fmt.Printf("Swap Used: %v MB (%.2f%%)\n", 
        swapStat.Used/1024/1024, swapStat.UsedPercent)

    return nil
}

func displayDiskInfo() error {
    partitions, err := disk.Partitions(false)
    if err != nil {
        return fmt.Errorf("error getting partitions: %w", err)
    }

    fmt.Println("\n=== Disk Information ===")
    for _, partition := range partitions {
        usageStat, err := disk.Usage(partition.Mountpoint)
        if err != nil {
            continue
        }

        fmt.Printf("\nDevice: %s\n", partition.Device)
        fmt.Printf("Mountpoint: %s\n", partition.Mountpoint)
        fmt.Printf("Filesystem: %s\n", partition.Fstype)
        fmt.Printf("Total: %v GB\n", usageStat.Total/1024/1024/1024)
        fmt.Printf("Used: %v GB (%.2f%%)\n", 
            usageStat.Used/1024/1024/1024, usageStat.UsedPercent)
        fmt.Printf("Free: %v GB\n", usageStat.Free/1024/1024/1024)
    }

    return nil
}

func main() {
    fmt.Println("System Monitor")
    fmt.Println("==============")

    if err := displayHostInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    if err := displayCPUInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    if err := displayMemoryInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }

    if err := displayDiskInfo(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}

Key Takeaways

CPU Monitoring

Use cpu.Percent() for usage and cpu.Counts() for core count.

Memory Stats

mem.VirtualMemory() and mem.SwapMemory() provide comprehensive memory data.

Disk Usage

Use disk.Partitions() to list drives and disk.Usage() to get usage stats.

System Info

host.Info() and host.Uptime() provide OS and uptime information.

Next Steps

Process Monitoring

Learn how to monitor and manage individual processes.

System Dashboard

Build a complete dashboard combining multiple monitoring features.

Build docs developers (and LLMs) love