← Ver a árvore completa

ROTA · 6 CLASSES · 1 GRUPOS

CLI Profissional

Crie uma ferramenta de terminal clara, previsível e pronta para uso real.

Pré-requisitos orientam, mas nunca bloqueiam. Cinco classes fundamentais e o bônus Go 1.27 são grátis com conta.

O ARCO DA ROTA

01CLI

ORDEM RECOMENDADA

6 classes, do primeiro passo ao fechamento.

Cada classe leva cerca de 15–25 minutos no novo formato de slides. Você pode sair da ordem quando outro nó fizer mais sentido.

  1. 01
    CLI ProfissionalFlags e argumentos: sua primeira CLI útil

    Crie uma CLI em Go com flags, defaults, ajuda e erros previsíveis usando o pacote flag.

  2. 02
    CLI ProfissionalSubcomandos: uma CLI que cresce sem virar um switch gigante

    Modele subcomandos em Go com FlagSets independentes, ajuda contextual e despacho testável.

  3. 03
    CLI ProfissionalConfig e env: precedência sem surpresas

    Combine defaults, configuração, ambiente e flags com uma regra de precedência explícita e testável.

  4. 04
    CLI Profissionalstdin, stdout e exit codes: o contrato com o shell

    Projete stdin, stdout, stderr e códigos de saída para uma CLI funcionar com pessoas e scripts.

  5. 05
    CLI ProfissionalOutput bonito com tabwriter, sem quebrar scripts

    Produza tabelas alinhadas com text/tabwriter e mantenha modos plain e JSON estáveis para automação.

  6. 06
    CLI ProfissionalCapstone: taskcli pronta para demonstrar no trabalho

    Monte uma task CLI completa com subcomandos, flags, env, stdin, formatos de saída, stderr e exit codes.

PRÉVIA DA PRIMEIRA CLASSE

Flags e argumentos: sua primeira CLI útil

// Dois tempos: registrar as flags, depois parsear.
nome := flag.String("nome", "mundo", "a quem cumprimentar")
vezes := flag.Int("vezes", 1, "quantas vezes repetir")

flag.Parse() // lê os.Args e preenche as variáveis

for i := 0; i < *vezes; i++ {
	fmt.Println("Olá,", *nome)
}

Você já recebeu um script que exige editar uma constante antes de cada uso. Para trocar o nome de entrada, abre o arquivo; para mudar o formato, altera outra linha; para descobrir as opções, procura no código. Uma CLI profissional move essas escolhas para a chamada. O executável permanece igual, enquanto flags como -name Bia descrevem o que varia naquela execução.

Pense no início do programa como a recepção de um prédio. Os tokens chegam em fila, mas ainda não têm significado. A recepção confere o crachá de cada um, converte valores para o tipo esperado e entrega uma ficha estruturada ao restante do sistema. O pacote flag faz essa triagem. Sem ela, cada comando inventa cortes de string, aceita grafias diferentes e produz erros incompatíveis.

Uma flag é uma opção nomeada, como -upper; um argumento posicional é um valor cuja função depende da posição. Flags comunicam melhor opções opcionais porque a ordem pode variar: -upper -name Bia e -name Bia -upper dizem a mesma coisa. Argumentos posicionais funcionam bem para entidades centrais, mas precisam de contrato explícito. Nesta primeira versão não aceitaremos nenhum posicional: qualquer sobra será erro, não entrada silenciosamente ignorada.

Em menos de dez minutos você terá um programa executável que aceita nome, aplica um valor padrão e transforma a saída. Rode go run . -name Bia -upper e obtenha OI, BIA!. Rode sem flags e obtenha Oi, mundo!. Esse primeiro ganho já serve para geradores, scripts internos e pequenos utilitários; o restante da aula fortalece erros e testabilidade.

A decisão importante é não acoplar parsing a os.Args nem à saída global. Um flag.FlagSet recebe um slice escolhido pelo chamador e pode escrever diagnósticos em um destino controlado. Isso permite testar a recepção com casos determinísticos no navegador, sem fingir um processo do sistema. A função principal fica responsável apenas por conectar a lógica ao processo real.

No programa abaixo, antes de rodar, preveja a saída com args := []string{"-times", "2", "-name", "Go"} e depois com args := []string{}. O valor padrão deve aparecer sem condição extra na aplicação. Em seguida, inverta a ordem das flags e confirme que o resultado não muda.

package main

import (
	"flag"
	"fmt"
)

func main() {
	args := []string{"-times", "2", "-name", "Go"}
	flags := flag.NewFlagSet("greet", flag.ContinueOnError)
	name := flags.String("name", "mundo", "nome")
	times := flags.Int("times", 1, "repetições")
	if err := flags.Parse(args); err != nil {
		fmt.Println("erro:", err)
		return
	}
	for index := 0; index < *times; index++ {
		fmt.Printf("Oi, %s!\n", *name)
	}
}
A introdução termina aqui

Entre para continuar nos slides, rodar o código e enfrentar os desafios.

Começar pela rota →

ESTA ROTA E TODAS AS OUTRAS

Qualquer plano abre os 192 nós.

Mensal R$19,90 · anual R$149 · lifetime R$499. Todos têm garantia de 7 dias.

Comparar os 3 planos →Começar pelas classes grátis