Practical examples of Go command-line application examples for 2025

If you’re hunting for practical, real-world examples of go command-line application examples, you’re in the right place. Go has quietly become a favorite for building fast, portable CLI tools that feel snappy even on older hardware. Instead of abstract theory, this guide walks through concrete, working examples of Go command-line application code you can actually steal, tweak, and ship. We’ll look at everything from tiny one-file utilities to more advanced tools with subcommands, configuration files, and structured logging. Along the way, you’ll see how each example of a Go CLI maps to real developer workflows: data inspection, automation, API scripting, DevOps tooling, and more. These are the kinds of examples include in modern engineering teams’ internal toolkits and open source projects. By the end, you’ll not only have several examples of Go command-line application examples to study, you’ll have patterns you can reuse across your own projects in 2024–2025.
Written by
Jamie
Published
Updated

Fast-start examples of Go command-line application examples

The best way to understand Go CLIs is to look at small, focused programs that solve a single problem well. These first examples of Go command-line application examples are intentionally minimal, but they already show off Go’s strengths: instant startup, easy cross-compilation, and type-safe standard libraries.

Example of a simple “echo with timestamp” CLI

This tiny tool prepends an ISO 8601 timestamp to whatever you pass on the command line:

package main

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

func main() {
    utc := flag.Bool("utc", false, "print time in UTC")
    flag.Parse()

    msg := strings.Join(flag.Args(), " ")
    if msg == "" {
        fmt.Fprintln(os.Stderr, "usage: ts [--utc] message")
        os.Exit(1)
    }

    now := time.Now()
    if *utc {
        now = now.UTC()
    }

    fmt.Printf("%s %s\n", now.Format(time.RFC3339), msg)
}

This is a classic starter in any list of examples of Go command-line application examples because it shows:

  • How to use the flag package
  • How to handle arguments after flags
  • How to print to stderr and exit with a non-zero status

You can imagine this being used in shell scripts to timestamp logs or quick notes.


Real examples include file utilities and JSON tools

A lot of the best examples of Go command-line application examples live in the space between “too small for a web service” and “too annoying to do by hand.” File processing and JSON inspection are perfect candidates.

Example of a JSON pretty-printer (jsonfmt)

Developers constantly poke at JSON from APIs. Here’s a simple CLI that reads JSON from stdin and prints it in a readable format:

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "io"
    "os"
)

func main() {
    compact := flag.Bool("compact", false, "output compact JSON")
    flag.Parse()

    data, err := io.ReadAll(os.Stdin)
    if err != nil {
        fmt.Fprintln(os.Stderr, "read error:", err)
        os.Exit(1)
    }

    var v any
    if err := json.Unmarshal(data, &v); err != nil {
        fmt.Fprintln(os.Stderr, "invalid JSON:", err)
        os.Exit(1)
    }

    var out []byte
    if *compact {
        out, err = json.Marshal(v)
    } else {
        out, err = json.MarshalIndent(v, "", "  ")
    }
    if err != nil {
        fmt.Fprintln(os.Stderr, "encode error:", err)
        os.Exit(1)
    }

    os.Stdout.Write(out)
    fmt.Println()
}

This kind of tool shows up constantly in real examples of Go command-line application examples used by backend engineers and SREs. It’s easy to extend with features like key filtering, colorized output, or schema validation.

Example of a directory size inspector (dirsize)

Another practical example of a Go CLI is a disk-usage helper that scans a directory and prints total size:

package main

import (
    "flag"
    "fmt"
    "os"
    "path/filepath"
)

func main() {
    path := flag.String("path", ".", "directory to scan")
    flag.Parse()

    var total int64

    err := filepath.Walk(*path, func(_ string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if !info.IsDir() {
            total += info.Size()
        }
        return nil
    })

    if err != nil {
        fmt.Fprintln(os.Stderr, "error:", err)
        os.Exit(1)
    }

    fmt.Printf("Total size under %s: %d bytes\n", *path, total)
}

This sits comfortably among the best examples of Go command-line application examples for local automation: fast, no dependencies, and portable across macOS, Linux, and Windows.


Modern examples of Go command-line application examples with subcommands

Once you outgrow single-purpose tools, you start wanting subcommands: tool server, tool client, tool user add, and so on. In 2024–2025, most production-grade Go CLIs lean on libraries like spf13/cobra to manage this complexity.

Example of a cobra-based multi-command CLI

This stripped-down example shows a CLI with hello and version subcommands:

// go.mod
// module example.com/mycli
// require github.com/spf13/cobra v1.8.0
// main.go
package main

import "example.com/mycli/cmd"

func main() {
    cmd.Execute()
}
// cmd/root.go
package cmd

import (
    "fmt"
    "os"

    "github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
    Use:   "mycli",
    Short: "MyCLI is a tiny demo tool",
}

func Execute() {
    if err := rootCmd.Execute(); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}
// cmd/hello.go
package cmd

import (
    "fmt"

    "github.com/spf13/cobra"
)

func init() {
    rootCmd.AddCommand(helloCmd)
}

var helloCmd = &cobra.Command{
    Use:   "hello [name]",
    Short: "Print a greeting",
    Args:  cobra.MaximumNArgs(1),
    Run: func(cmd *cobra.Command, args []string) {
        name := "world"
        if len(args) == 1 {
            name = args[0]
        }
        fmt.Printf("Hello, %s!\n", name)
    },
}
// cmd/version.go
package cmd

import (
    "fmt"

    "github.com/spf13/cobra"
)

var version = "v0.1.0"

func init() {
    rootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
    Use:   "version",
    Short: "Print version information",
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println(version)
    },
}

When people talk about production-ready examples of Go command-line application examples, this pattern is what they usually mean: a structured project, clean commands, and room to grow.

For a real-world reference, the Kubernetes kubectl tool is written in Go using similar ideas, and the Go team maintains guidance on CLI design patterns in the official docs at go.dev.


Best examples of Go command-line application examples for DevOps and SRE

DevOps and SRE teams love Go because static binaries are easy to ship into containers or drop onto servers. Some of the best examples of Go command-line application examples in this space include health check tools, log processors, and API pingers.

Example of an HTTP health-check CLI (healthcheck)

Imagine you want a simple tool for CI pipelines that verifies an HTTP endpoint is healthy before running tests:

package main

import (
    "flag"
    "fmt"
    "net/http"
    "os"
    "time"
)

func main() {
    url := flag.String("url", "", "URL to check")
    timeout := flag.Duration("timeout", 5*time.Second, "request timeout")
    expect := flag.Int("expect", 200, "expected HTTP status code")
    flag.Parse()

    if *url == "" {
        fmt.Fprintln(os.Stderr, "--url is required")
        os.Exit(1)
    }

    client := &http.Client{Timeout: *timeout}

    resp, err := client.Get(*url)
    if err != nil {
        fmt.Fprintln(os.Stderr, "request failed:", err)
        os.Exit(1)
    }
    defer resp.Body.Close()

    if resp.StatusCode != *expect {
        fmt.Fprintf(os.Stderr, "unexpected status: got %d, want %d\n", resp.StatusCode, *expect)
        os.Exit(1)
    }

    fmt.Println("OK")
}

This is the sort of example of a Go CLI that gets baked into CI/CD pipelines, Kubernetes readiness checks, or deployment scripts.

For broader context on health checks and monitoring patterns, you can compare this approach with best practices from the U.S. National Institute of Standards and Technology (NIST) in their guidance on secure system design at nist.gov.

Example of a log filter CLI with regex support

Another realistic example of Go command-line application examples is a log filtering helper that reads from stdin, matches a regular expression, and prints only matching lines:

package main

import (
    "bufio"
    "flag"
    "fmt"
    "os"
    "regexp"
)

func main() {
    pattern := flag.String("pattern", "", "regular expression to match")
    invert := flag.Bool("invert", false, "invert match")
    flag.Parse()

    if *pattern == "" {
        fmt.Fprintln(os.Stderr, "--pattern is required")
        os.Exit(1)
    }

    re, err := regexp.Compile(*pattern)
    if err != nil {
        fmt.Fprintln(os.Stderr, "invalid regex:", err)
        os.Exit(1)
    }

    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        line := scanner.Text()
        match := re.MatchString(line)
        if match != *invert {
            fmt.Println(line)
        }
    }

    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "read error:", err)
        os.Exit(1)
    }
}

In 2024–2025, teams increasingly standardize on Go for this kind of tooling because the binaries are small, there is no runtime dependency, and performance is consistent across platforms.


API and data automation: more real examples of Go command-line application examples

Modern engineering teams lean heavily on APIs, and Go’s HTTP and JSON support makes it a natural fit for scripting data workflows. These real examples of Go command-line application examples show how to glue together web services and local files.

Example of an API client CLI that writes CSV

Suppose you call a public JSON API and want to turn the result into a CSV file for analysis. Here’s a simplified pattern:

package main

import (
    "encoding/csv"
    "encoding/json"
    "flag"
    "fmt"
    "net/http"
    "os"
)

type Item struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

func main() {
    url := flag.String("url", "", "JSON API endpoint returning a list of items")
    out := flag.String("out", "out.csv", "output CSV file")
    flag.Parse()

    if *url == "" {
        fmt.Fprintln(os.Stderr, "--url is required")
        os.Exit(1)
    }

    resp, err := http.Get(*url)
    if err != nil {
        fmt.Fprintln(os.Stderr, "request error:", err)
        os.Exit(1)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        fmt.Fprintln(os.Stderr, "unexpected status:", resp.Status)
        os.Exit(1)
    }

    var items []Item
    if err := json.NewDecoder(resp.Body).Decode(&items); err != nil {
        fmt.Fprintln(os.Stderr, "decode error:", err)
        os.Exit(1)
    }

    f, err := os.Create(*out)
    if err != nil {
        fmt.Fprintln(os.Stderr, "create error:", err)
        os.Exit(1)
    }
    defer f.Close()

    w := csv.NewWriter(f)
    defer w.Flush()

    w.Write([]string{"id", "name", "email"})
    for _, it := range items {
        row := []string{fmt.Sprint(it.ID), it.Name, it.Email}
        if err := w.Write(row); err != nil {
            fmt.Fprintln(os.Stderr, "write error:", err)
            os.Exit(1)
        }
    }

    fmt.Println("Wrote", *out)
}

This example of a Go CLI bridges JSON APIs and data analysis tools like spreadsheets or Python notebooks. You’ll see patterns like this in real-world data engineering pipelines, health data exports, and research workflows. For example, public health APIs from organizations like the Centers for Disease Control and Prevention (cdc.gov) can be queried and transformed with similar tools for downstream analysis.

Example of a configuration-aware CLI with environment overrides

In 2025, developers expect CLIs to read configuration files and environment variables, not just flags. Here’s a small example of Go command-line application examples that respect both:

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "os"
)

type Config struct {
    Endpoint string `json:"endpoint"`
    Token    string `json:"token"`
}

func loadConfig(path string) (*Config, error) {
    f, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer f.Close()

    var cfg Config
    if err := json.NewDecoder(f).Decode(&cfg); err != nil {
        return nil, err
    }
    return &cfg, nil
}

func main() {
    cfgPath := flag.String("config", "config.json", "path to config file")
    flag.Parse()

    cfg, err := loadConfig(*cfgPath)
    if err != nil {
        fmt.Fprintln(os.Stderr, "config error:", err)
        os.Exit(1)
    }

    if v := os.Getenv("MYCLI_ENDPOINT"); v != "" {
        cfg.Endpoint = v
    }
    if v := os.Getenv("MYCLI_TOKEN"); v != "" {
        cfg.Token = v
    }

    if cfg.Endpoint == "" || cfg.Token == "" {
        fmt.Fprintln(os.Stderr, "endpoint and token must be set")
        os.Exit(1)
    }

    fmt.Println("Using endpoint:", cfg.Endpoint)
    // Perform work with cfg.Endpoint and cfg.Token...
}

Patterns like this show up in internal tools that talk to private APIs, cloud services, or research data platforms. Universities and research institutions, such as those documented on harvard.edu, frequently use similar CLI patterns for reproducible data workflows.


Observability and logging: examples include structured logs and metrics

As Go CLIs become more central to production workflows, observability matters. Modern examples of Go command-line application examples increasingly use structured logging and metrics so they can be monitored like any other service.

Example of structured JSON logging for a CLI

Here is a simplified pattern using the standard library to emit JSON logs that can be consumed by tools like jq or centralized log systems:

package main

import (
    "encoding/json"
    "fmt"
    "os"
    "time"
)

type LogEntry struct {
    Level   string    `json:"level"`
    Time    time.Time `json:"time"`
    Message string    `json:"message"`
    Task    string    `json:"task,omitempty"`
    Error   string    `json:"error,omitempty"`
}

func log(level, msg string, fields map[string]string) {
    entry := LogEntry{
        Level:   level,
        Time:    time.Now().UTC(),
        Message: msg,
    }
    if task, ok := fields["task"]; ok {
        entry.Task = task
    }
    if err, ok := fields["error"]; ok {
        entry.Error = err
    }

    b, _ := json.Marshal(entry)
    fmt.Println(string(b))
}

func main() {
    log("info", "starting backup", map[string]string{"task": "backup"})

    // ... do some work ...

    if err := doWork(); err != nil {
        log("error", "backup failed", map[string]string{
            "task":  "backup",
            "error": err.Error(),
        })
        os.Exit(1)
    }

    log("info", "backup completed", map[string]string{"task": "backup"})
}

func doWork() error {
    // placeholder for real work
    return nil
}

This pattern makes it easy to integrate CLI output with observability stacks that expect structured data. It’s a recurring example of Go command-line application examples in modern SRE playbooks.

For more general background on logging and monitoring practices in critical systems, NIST and other U.S. agencies provide guidance at nist.gov.


FAQ: common questions about examples of Go command-line application examples

What are some real-world examples of Go command-line application examples?

Real-world examples include tools like kubectl for Kubernetes, helm for package management, hugo for static site generation, and many internal DevOps utilities for health checks, log processing, and API automation. All of these follow the same patterns you’ve seen in the examples of Go command-line application examples above: flags, subcommands, configuration, and structured output.

How do I choose between the flag package and libraries like cobra?

Use the standard flag package for small, focused tools with a handful of options. When you need subcommands, rich help text, shell completion, or a long-term CLI roadmap, libraries such as cobra become more attractive. Many of the best examples of Go command-line application examples in open source use cobra or similar frameworks to keep things maintainable.

Is Go still a good choice for new CLI tools in 2024–2025?

Yes. Go’s static binaries, fast startup, and strong standard library make it a solid choice for new CLIs. The ecosystem around testing, cross-compilation, and packaging has matured significantly, and there are many fresh examples of Go command-line application examples on GitHub that target modern workflows like cloud automation, container orchestration, and data engineering.

Where can I find more example of Go CLI code to study?

Browsing popular repositories on GitHub that are tagged with go and cli is a good starting point. You can also study the Go team’s own tools and tutorials at go.dev, and look at how large projects structure their commands and flags. Combining those references with the examples of Go command-line application examples in this guide will give you a strong mental model for designing your own tools.

How should I test my Go command-line applications?

Treat your CLI as a library plus a thin main wrapper. Put most logic into packages that you can test with standard Go unit tests, and keep main primarily for wiring flags and I/O. Many of the best examples of Go command-line application examples follow this approach, which keeps behavior testable and avoids brittle tests that depend on exact console output formatting.

Explore More Go Code Snippets

Discover more examples and insights in this category.

View All Go Code Snippets