Go — não é apenas uma linguagem da moda, mas uma ferramenta para desenvolvimento rápido
\n\nGo (ou Golang) nos últimos anos se transformou de uma linguagem exótica em um padrão da indústria para backend, microsserviços e aplicações em nuvem. Seus criadores (Rob Pike, Ken Thompson) propositalmente tornaram a linguagem simples, mas o diabo, como sempre, está nos detalhes. Muitos iniciantes ficam presos na fase "eu escrevi Hello World, e agora?".
\n\nNeste artigo, reuni dicas de desenvolvedores seniores que ajudarão você não apenas a aprender a sintaxe do Go, mas a acelerar o aprendizado de Go e começar a escrever código pronto para produção. Vamos analisar casos reais, erros típicos e dar itens de ação concretos. Vamos lá!
\n\n1. Esqueça a "POO do Java" — pense em composição
\n\nO erro mais comum de iniciantes é tentar encaixar a POO clássica (herança, polimorfismo de classes) no Go. Go não tem classes nem herança. Em vez disso — structs e interfaces.
\n\nDesenvolvedores seniores aconselham: aprenda Go através da composição. Incorpore uma struct em outra, use interfaces para abstração.
\n\nExemplo: como NÃO fazer
\n// Ruim: tentativa de fazer "herança" através de incorporação com sobrescrita de métodos\ntype Animal struct {\n Name string\n}\nfunc (a Animal) Speak() string {\n return "I am an animal"\n}\n\ntype Dog struct {\n Animal\n}\nfunc (d Dog) Speak() string {\n return "Woof!"\n}\n\n\nExemplo: como fazer (composição + interfaces)
\n// Bom: usamos interface e composição\ntype Speaker interface {\n Speak() string\n}\n\ntype Dog struct {\n Name string\n}\n\nfunc (d Dog) Speak() string {\n return "Woof! I'm " + d.Name\n}\n\nfunc MakeSound(s Speaker) {\n fmt.Println(s.Speak())\n}\n\nfunc main() {\n dog := Dog{Name: "Rex"}\n MakeSound(dog) // Funciona com qualquer Speaker\n}\n\n\nDica de sênior: "Comece com interface{} — é a interface vazia. Entenda como Go verifica tipos através de type assertion. Isso economizará semanas."
2. Goroutines não são apenas "go func()"
\n\nGoroutines são a killer feature do Go. Mas iniciantes frequentemente escrevem:
\ngo myFunc()\n// ... e esquecem a sincronização\n\n\nIsso leva a condições de corrida (data races). Desenvolvedores seniores aconselham sempre usar sync.WaitGroup ou canais para sincronização.
Padrão correto: Worker Pool
\npackage main\n\nimport (\n "fmt"\n "sync"\n "time"\n)\n\nfunc worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {\n defer wg.Done()\n for j := range jobs {\n fmt.Printf("Worker %d processing job %d\\n", id, j)\n time.Sleep(time.Second) // simulação de trabalho\n results <- j * 2\n }\n}\n\nfunc main() {\n const numJobs = 5\n jobs := make(chan int, numJobs)\n results := make(chan int, numJobs)\n var wg sync.WaitGroup\n\n // Inicia 3 workers\n for w := 1; w <= 3; w++ {\n wg.Add(1)\n go worker(w, jobs, results, &wg)\n }\n\n // Envia tarefas\n for j := 1; j <= numJobs; j++ {\n jobs <- j\n }\n close(jobs)\n\n // Aguarda a conclusão de todos os workers\n wg.Wait()\n close(results)\n\n // Coleta os resultados\n for r := range results {\n fmt.Println("Result:", r)\n }\n}\n\n\nPor que isso acelera o aprendizado de Go? Você aprende imediatamente a trabalhar com goroutines de forma segura, sem vazamentos e pânicos.
\n\n3. Erros são valores (errors are values)
\n\nGo não tem exceções (try-catch). Erros são apenas valores que precisam ser tratados. Desenvolvedores seniores gravam isso na cabeça já nas primeiras revisões de código.
\n\nErro típico de iniciante:
\nresult, _ := doSomething() // Ignorando o erro\n\n\nComo fazer:
\nresult, err := doSomething()\nif err != nil {\n // Loga, retorna, entra em pânico (mas n