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
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.
- 01CLI ProfissionalFlags e argumentos: sua primeira CLI útil
Crie uma CLI em Go com flags, defaults, ajuda e erros previsíveis usando o pacote flag.
- 02CLI ProfissionalSubcomandos: uma CLI que cresce sem virar um switch gigante
Modele subcomandos em Go com FlagSets independentes, ajuda contextual e despacho testável.
- 03CLI 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.
- 04CLI 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.
- 05CLI ProfissionalOutput bonito com tabwriter, sem quebrar scripts
Produza tabelas alinhadas com text/tabwriter e mantenha modos plain e JSON estáveis para automação.
- 06CLI 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)
}
}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.