What do you do if you need to get the usage of your host’s hard disk, CPU, memory, processes, etc. in Golang? A simple idea would be to run some commands like ps, cd, top through os/exec and then parse the results of those commands.

Of course, based on the Linux idea that everything is a file, a more straightforward approach would be to read the contents of the relevant files, such as those in the /proc directory.

The above approach can fulfill the requirements, but we don’t have to duplicate the creation of tools, because there is already a fairly well-developed three-way library that implements these collection requirements for us, and it is gopsutil.

Introduction to gopsutil

psutil (process and system utilities,) is a cross-platform library for getting process and system utilization (CPU, memory, disk, network, sensors) information in Python, and gopsutil is the Go language version of it.

gopsutil shields us from the differences between systems. It has good portability.

The following systems are supported.

  • FreeBSD i386/amd64/arm
  • Linux i386/amd64/arm(raspberry pi)
  • Windows i386/amd64/arm/arm64
  • Darwin i386/amd64
  • OpenBSD amd64
  • Solaris amd64

Partial Support List.

  • CPU on DragonFly BSD
  • host on Linux RISC-V

In addition, by porting C structures to Go structures, the project has no cgo code in its implementation, which makes it easier to cross-compile.

Usage

There are v3 and v2 versions of gopsutil available and no backward compatibility guarantees, so there are two ways to use it.

1
2
3
4
import (
    // "github.com/shirou/gopsutil/v3/mem" // to use v3
    "github.com/shirou/gopsutil/mem"  
)

For example, if we want to view system memory usage information, we can get it in the following way.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import (
    "fmt"

    "github.com/shirou/gopsutil/v3/mem"
    // "github.com/shirou/gopsutil/mem"  // to use v2
)

func main() {
    v, _ := mem.VirtualMemory()

    // almost every return value is a struct
    fmt.Printf("Total: %v, Free:%v, UsedPercent:%f%%\n", v.Total, v.Free, v.UsedPercent)

    // convert to JSON. String() is also implemented
    fmt.Println(v)
}

The results of the run are as follows.

1
2
Total: 8589934592, Free:138248192, UsedPercent:76.416254%
{"total":8589934592,"available":2025828352,"used":6564106240,"usedPercent":76.4162540435791,"free":138248192,"active":1949327360,"inactive":1887580160,"wired":2214510592,"laundry":0,"buffers":0,"cached":0,"writeBack":0,"dirty":0,"writeBackTmp":0,"shared":0,"slab":0,"sreclaimable":0,"sunreclaim":0,"pageTables":0,"swapCached":0,"commitLimit":0,"committedAS":0,"highTotal":0,"highFree":0,"lowTotal":0,"lowFree":0,"swapTotal":0,"swapFree":0,"mapped":0,"vmallocTotal":0,"vmallocUsed":0,"vmallocChunk":0,"hugePagesTotal":0,"hugePagesFree":0,"hugePageSize":0}

One friendly aspect of the gopsutil package is that most of the collection functions return a structure object, which implements the fmt.Stringer interface, so they will be output in json format when printed.

For example, the mem.VirtualMemory example above returns a VirtualMemoryStat structure, which calls the json.Marshal() function in the String() method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
type VirtualMemoryStat struct {
 Total uint64 `json:"total"`
 Available uint64 `json:"available"`
 Used uint64 `json:"used"`
 UsedPercent float64 `json:"usedPercent"`
 Free uint64 `json:"free"`
 Active   uint64 `json:"active"`
 Inactive uint64 `json:"inactive"`
 Wired    uint64 `json:"wired"`

func (m VirtualMemoryStat) String() string {
 s, _ := json.Marshal(m)
 return string(s)
}

gopsutil is divided into different sub-packages according to different acquisition units, and the relevant methods can be called by introducing different sub-packages in use.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import (
 "github.com/shirou/gopsutil/v3/mem"
 "github.com/shirou/gopsutil/v3/cpu"
 "github.com/shirou/gopsutil/v3/disk"
 "github.com/shirou/gopsutil/v3/docker"
 "github.com/shirou/gopsutil/v3/host"
 "github.com/shirou/gopsutil/v3/internal"
 "github.com/shirou/gopsutil/v3/load"
 "github.com/shirou/gopsutil/v3/mem"
 "github.com/shirou/gopsutil/v3/net"
 "github.com/shirou/gopsutil/v3/process"
 "github.com/shirou/gopsutil/v3/winservices"
)

For example, if we want to get the host information, we need to import the github.com/shirou/gopsutil/v3/host subpackage.

1
2
3
4
5
6
7
8
9
import (
 "fmt"
 "github.com/shirou/gopsutil/v3/host"
)

func main() {
 hostInfo, _ := host.Info()
 fmt.Println(hostInfo)
}

Output:

1
{"hostname":"MacBook-Pro.local","uptime":1619284,"bootTime":1644332729,"procs":301,"os":"darwin","platform":"darwin","platformFamily":"Standalone Workstation","platformVersion":"10.15.5","kernelVersion":"19.5.0","kernelArch":"x86_64","virtualizationSystem":"","virtualizationRole":"","hostId":"7a1a74f2-30fc-4cc1-b439-6b7aef22e45d"}

Summary

The gopsutil library has very comprehensive coverage units, including host, disk, memory, CPU, network, process, docker and other modules, it can help us get system information very well. And gopsutil handles cross-platform compatibility issues, the external interface is basically consistent and friendly to use.

The library will help you in scenarios such as information gathering, system monitoring, resource limitation, process management, etc.