Practical examples of Go command-line application examples for 2025
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
flagpackage - 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.
Related Topics
Practical examples of Go command-line application examples for 2025
Practical examples of 3 examples of working with Go maps for real projects
Practical examples of simple HTTP server examples in Go
Practical examples of defining and using structs in Go
Practical examples of creating and using Go interfaces
So You Think You Know HTTP in Go? Think Again
Explore More Go Code Snippets
Discover more examples and insights in this category.
View All Go Code Snippets