Skip to content
shellhacks.dev
Go

Read command line flags

Read command line options with the flag package: flag.String, flag.Int and flag.Bool, then flag.Parse(). Parsing stops at the first argument that is not a flag.

2 min read
Summarize in AI

A command line tool needs named options with defaults, and options placed after a file name are not seen.

main.goGo
package main

import (
	"flag"
	"fmt"
)

func main() {
	name := flag.String("name", "world", "who to greet")
	times := flag.Int("n", 1, "how many times")
	loud := flag.Bool("loud", false, "shout")
	flag.Parse()
	for i := 0; i < *times; i++ {
		msg := "hello " + *name
		if *loud {
			msg += "!"
		}
		fmt.Println(msg)
	}
	fmt.Println("args:", flag.Args())
}
Shell
go build -o greet main.go
./greet -name Ada -n 2 -loud extra
echo ---
./greet extra -n 2
echo ---
./greet -loud=false -name=Bob
echo ---
./greet -n abc 2>&1 | head -2
Text
hello Ada!
hello Ada!
args: [extra]
---
hello world
args: [extra -n 2]
---
hello Bob
args: []
---
invalid value "abc" for flag -n: parse error
Usage of ./greet:

Each constructor registers an option and returns a pointer, which is filled by flag.Parse. The first run uses the usual forms. The second shows the rule people trip on: parsing ends at the first non-flag argument, so -n 2 after extra is left in flag.Args() and the count stays at 1. A boolean flag takes a value only in the -loud=false form, never as a separate word. Both rules come from the flag package. A bad value prints the error and the usage and exits with status 2.

The package accepts one or two dashes for any option and has no short and long aliases, no grouping like -xvf and no subcommands; for those use FlagSet per subcommand, or a library such as cobra. Put the flags before the positional arguments in documentation and in scripts that call the tool.

Taggedgo
Share

More snippets

Go

Exit with a status

Exit with a status using os.Exit(n). It ends the program at once and skips every deferred call, so cleanup in defer is not run before the exit.

1 min read
Go

Raise the scanner line limit

Raise the line limit of bufio.Scanner with Buffer(make([]byte, 0, 64*1024), max). Lines over 64 KB otherwise stop the scan with token too long.

1 min read
Go

Set a timeout for a command

Stop a command that takes too long with exec.CommandContext and context.WithTimeout. In Go 1.19 a shell's child can keep Output() waiting past the deadline.

2 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.