Argumentos de la línea de órdenes en Go

Go trae en la biblioteca estándar todo lo necesario para leer argumentos: os.Args para lo más básico y el paquete flag en cuanto quieras opciones con nombre. Ninguno de los dos necesita dependencias.

Lo mínimo: os.Args

Todo lo que se escribe tras el nombre del programa llega en un slice de cadenas. La posición 0 es el propio programa.

package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println("programa:", os.Args[0])
	fmt.Println("argumentos:", os.Args[1:])
}
./args uno dos tres
salidaprograma: ./args
argumentos: [uno dos tres]

Sirve para casos muy sencillos. En cuanto quieras opciones con nombre, valores por defecto o una ayuda, hay algo mejor y viene de serie.

Opciones con nombre: el paquete flag

package main

import (
	"flag"
	"fmt"
)

func main() {
	nombre := flag.String("nombre", "mundo", "a quién saludar")
	veces := flag.Int("veces", 1, "cuántas veces")
	mayus := flag.Bool("mayus", false, "en mayúsculas")
	flag.Parse()

	saludo := "Hola, " + *nombre
	if *mayus {
		saludo = "HOLA, " + *nombre
	}
	for i := 0; i < *veces; i++ {
		fmt.Println(saludo)
	}

	if resto := flag.Args(); len(resto) > 0 {
		fmt.Println("argumentos sueltos:", resto)
	}
}

Cada flag.Algo recibe el nombre de la opción, su valor por defecto y la descripción, y devuelve un puntero. Por eso luego hay que leerlos con asterisco: *nombre. Nada funciona hasta que se llama a flag.Parse().

./saludo
./saludo -nombre Ana -veces 2
./saludo -nombre Ana -mayus archivo1.txt archivo2.txt
salidaHola, mundo
Hola, Ana
Hola, Ana
HOLA, Ana
argumentos sueltos: [archivo1.txt archivo2.txt]

flag.Args() recoge lo que sobra una vez retiradas las opciones: los nombres de archivo, normalmente.

La ayuda sale gratis

./saludo -h
salidaUsage of ./saludo:
  -mayus
    	en mayúsculas
  -nombre string
    	a quién saludar (default "mundo")
  -veces int
    	cuántas veces (default 1)

No hay que escribirla: la construye flag con las descripciones que ya diste. Y si alguien pasa una opción que no existe, el programa se planta solo:

salidaflag provided but not defined: -color
Usage of ./saludo:
  -mayus
Un guion o dos, da igual. flag acepta -nombre y --nombre indistintamente, y también -nombre=Ana. Lo que no acepta es agrupar opciones cortas al estilo de Unix: -abc no equivale a -a -b -c. Si necesitas eso, hay bibliotecas externas como spf13/cobra, que es la que usan Docker y Kubernetes.

Cuál usar

Lo que necesitas Lo que conviene
Uno o dos valores posicionales os.Args[1:]
Opciones con nombre y valores por defecto flag, de la biblioteca estándar
Subcomandos al estilo git commit flag.NewFlagSet, o una biblioteca externa
Una herramienta grande, con autocompletado spf13/cobra

Todo el código de esta página se compiló y ejecutó con Go 1.25 antes de publicarla; las salidas están copiadas de esa ejecución, incluidos la ayuda generada y el error de la opción inexistente. Documentación oficial: paquete flag.