Understanding gopsutils's cpu.Info()

gopsutil is a port of psutil written in Go. I won’t get into details about what these modules are all about. They both have pros and cons.

Back then, coming from an interpreted lanaguage like Python, gave me hard time understanding how to work with a compiled language like Go. I thought it would be nice to write something about this. I will keep it as short as possible.

func Info()

The Info() function returns two values of types:

  • []InfoStat - a slice of type Infostat

  • and an error

[InfoStat] is a JSON encoded struct:

type InfoStat struct {
	CPU        int32    `json:"cpu"`
	VendorID   string   `json:"vendorId"`
	Family     string   `json:"family"`
	Model      string   `json:"model"`
	Stepping   int32    `json:"stepping"`
	PhysicalID string   `json:"physicalId"`
	CoreID     string   `json:"coreId"`
	Cores      int32    `json:"cores"`
	ModelName  string   `json:"modelName"`
	Mhz        float64  `json:"mhz"`
	CacheSize  int32    `json:"cacheSize"`
	Flags      []string `json:"flags"`
	Microcode  string   `json:"microcode"`
}

Info() is basically returning a slice of JSON encoded data:

[{"cpu":0,"vendorId":"GenuineIntel","family":"6","model":"58","stepping":9,"physicalId":"","coreId":"","cores":2,"modelName":"Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz","mhz":2500,"cacheSize":256,"flags":["fpu","vme","de","pse","tsc","msr","pae","mce","cx8","apic","sep","mtrr","pge","mca","cmov","pat","pse36","clfsh","ds","acpi","mmx","fxsr","sse","sse2","ss","htt","tm","pbe","sse3","pclmulqdq","dtes64","mon","dscpl","vmx","est","tm2","ssse3","cx16","tpr","pdcm","sse4.1","sse4.2","x2apic","popcnt","aes","pcid","xsave","osxsave","tsctmr","avx1.0","rdrand","f16c","rdwrfsgs","smep","erms","mdclear","ibrs","stibp","l1df","ssbd","syscall","xd","em64t","lahf","rdtscp","tsci"],"microcode":""}]

Now, how do I call specific field like VendorID or ModelName ? The key is all about data types. As long as you understand what data type a particular function is returning, you’ll do fine. Since the whole output is a slice, let’s get the first and only index:

a, _ := cpu.Info() // returns a slice and leave off the error
b := a[0] // get first index
fmt.Println(b) // prints the output

The output is same as above, but without the square brackets. b is now holding a struct instead of a slice.

Specific field can be called:

fmt.Println("Vendor ID:", b.VendorID)
fmt.Println("Model:", b.ModelName)

Job done:

Vendor ID: GenuineIntel
Model: Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz

Here’s a simple function to get the underlying type of multiple values in case you loss track of what you’re doing:

func getMultipleType(x ...interface{}) {
	for _, v := range x {
		result := reflect.TypeOf(v).Kind() // get the underlying type of a value
		// fmt.Println(v, "is a", result)
		fmt.Println(result)
	}

Full code:

package main

import (
	"fmt"
	"github.com/shirou/gopsutil/cpu"
	"reflect"
)

func main(){

	a, _ := cpu.Info() 
	b := a[0] 

	fmt.Println("Vendor ID:", b.VendorID) 
	fmt.Println("Model:", b.ModelName) 

	getMultipleType(a, b) // will print "slice" and "struct"

}

func getMultipleType(x ...interface{}) {
	for _, v := range x {
		result := reflect.TypeOf(v).Kind()
		fmt.Println(result)
	}
}

“The most disastrous thing that you can ever learn is your first programming language.” ― Alan Kay