Frontend Labs
⋯

13. Terminal project: a system-info CLI and unit converter

Goal: tie together Chapters 1–12 into one small, real binary you run from your shell today.

// cmd/sysinfo/main.go
package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"time"
)

type ByteUnit int64

const (
	Byte ByteUnit = 1
	KB            = Byte * 1024
	MB            = KB * 1024
	GB            = MB * 1024
)

func humanize(bytes uint64) string {
	switch {
	case bytes >= uint64(GB):
		return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB))
	case bytes >= uint64(MB):
		return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB))
	case bytes >= uint64(KB):
		return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB))
	default:
		return fmt.Sprintf("%d B", bytes)
	}
}

func main() {
	jsonOut := flag.Bool("json", false, "print as JSON")
	flag.Parse()

	host, err := os.Hostname()
	if err != nil {
		host = "unknown"
	}

	var mem runtime.MemStats
	runtime.ReadMemStats(&mem)

	report := struct {
		Host      string `json:"host"`
		GoVersion string `json:"go_version"`
		CPUs      int    `json:"cpus"`
		Goroutines int   `json:"goroutines"`
		HeapAlloc string `json:"heap_alloc"`
		Timestamp string `json:"timestamp"`
	}{
		Host:       host,
		GoVersion:  runtime.Version(),
		CPUs:       runtime.NumCPU(),
		Goroutines: runtime.NumGoroutine(),
		HeapAlloc:  humanize(mem.HeapAlloc),
		Timestamp:  time.Now().Format(time.RFC3339),
	}

	if *jsonOut {
		printJSON(report)
		return
	}
	fmt.Printf("host:       %s\n", report.Host)
	fmt.Printf("go version: %s\n", report.GoVersion)
	fmt.Printf("cpus:       %d\n", report.CPUs)
	fmt.Printf("goroutines: %d\n", report.Goroutines)
	fmt.Printf("heap:       %s\n", report.HeapAlloc)
	fmt.Printf("time:       %s\n", report.Timestamp)
}
go run ./cmd/sysinfo
go run ./cmd/sysinfo --json | jq .

This is deliberately the same exercise as Day 1 of the 90-day plan, but carried one step further with a --json flag — your first taste of the flag package that Chapter 40 builds into full subcommand CLIs.


Generated from real-life-golang-guide.md · 8 Oct 2026 16:36