Entrevistas de Go focam em goroutines, channels, interfaces e tratamento de erros — a linguagem é pequena, então as perguntas vão fundo em vez de largo. Abaixo estão as mais comuns com respostas modelo. Middle: compreensão mais profunda, otimização e situações reais de trabalho.
1
Qual é a diferença entre um channel com buffer e um sem buffer?
Resposta
Um channel sem buffer sincroniza: o envio bloqueia até que um receptor pegue o valor, então os dois lados se encontram. Um channel com buffer aceita até sua capacidade sem um receptor, e bloqueia só quando está cheio. Sem buffer é o padrão mais seguro porque torna o handoff explícito; um buffer é uma decisão sobre quanto trabalho pode se acumular.
2
Quando uma goroutine vaza, e como você perceberia isso?
Resposta
Quando ela bloqueia para sempre num channel que ninguém vai ler ou escrever, ou espera num context que nunca é cancelado. Você percebe por uma contagem de goroutines que sobe e nunca desce — runtime.NumGoroutine() ou o profile de goroutines do pprof, que mostra exatamente onde estão estacionadas. A causa mais comum é um produtor que retorna cedo demais e deixa um consumidor esperando.
3
Para que serve o `context`?
Resposta
Carregar um deadline, um sinal de cancelamento e valores com escopo de request através das fronteiras da API. O trabalho real dele é o cancelamento: quando um request é abandonado, tudo que ele iniciou deveria parar em vez de continuar trabalhando para ninguém. A regra que o mantém útil é que context é o primeiro parâmetro e nunca é guardado num struct.
4
Como um `select` com `default` se comporta diferente de um sem?
Resposta
Sem default, select bloqueia até que um dos seus cases esteja pronto. Com default, ele toma o default imediatamente se mais nada estiver, tornando a operação não bloqueante. Um default dentro de um loop sem nenhum outro bloqueio é um busy-wait que vai girar um core, que é o erro a se vigiar.
5
O que o race detector encontra, e o que ele não encontra?
Resposta
Ele encontra acesso concorrente à mesma memória onde pelo menos um lado é uma escrita, nos caminhos de código que foram de fato executados durante a corrida. O que ele não encontra é a race que você não exercitou — é uma ferramenta de runtime, não uma prova. Por isso ele pertence ao CI rodando contra testes reais, em vez de ser executado uma vez manualmente.
6
Como você decide entre um mutex e um channel?
Resposta
Um mutex protege estado compartilhado; um channel transfere a posse de dados. Se várias goroutines leem e escrevem uma estrutura, um mutex é mais simples e rápido. Se o trabalho se move de uma goroutine para outra, um channel expressa isso diretamente. Recorrer a um channel para proteger um contador é uma supercomplicação comum.
7
O que o `sync.WaitGroup` garante, e como ele é usado errado?
Resposta
Que Wait retorna assim que o contador chega a zero, então você sabe que cada goroutine rastreada terminou. Os dois usos incorretos clássicos são chamar Add dentro da goroutine, o que gera uma race com Wait, e passar o WaitGroup por valor, o que o copia e deixa o contador original intacto. Os dois compilam e os dois falham de forma intermitente.