Contador
.Incrementa
.Contador
, vamos escrever uma pequena função de asserção verificaContador
para que o teste fique um pouco mais legível.contagemEsperada
e disparar uma goroutine para chamar contador.Incrementa()
a cada iteração.Um WaitGroup aguarda por uma coleção de goroutines terminar seu processamento. A goroutine principal faz a chamada para oAdd
definir o número de goroutines que serão esperadas. Então, cada uma das goroutines é executada e chamaDone
quando termina sua execução. Ao mesmo tempo,Wait
pode ser usado para bloquear a execução até que todas as goroutines tenham terminado.
wg.Wait()
terminar sua execução antes de fazer nossas asserções, podemos ter certeza que todas as nossas goroutines tentaram chamar o Incrementa
no Contador
.Um Mutex é uma trava de exclusão mútua. O valor zero de um Mutex é um Mutex destravado.
Incrementa
vai receber a trava em Contador
se for a primeira chamando essa função. Todas as outras goroutines vão ter que esperar por essa primeira execução até que ele esteja Unlock
, ou destravado, antes de ganhar o acesso à instância de Contador
alterada pela primeira chamada de função.sync.Mutex
está embutido dentro da struct.Lock
e Unlock
é, no seu melhor caso, muito confuso e, no seu pior caso, potencialmente perigoso para o seu software se quem chamar o seu tipo começar a chamar esses métodos diretamente.go vet
no seu código, deve receber um erro similar ao seguinte:Um Mutex não deve ser copiado depois do primeiro uso.
Contador
(por valor) para verificaContador
, ele vai tentar criar uma cópia do mutex.Contador
. Vamos, então, mudar a assinatura de verificaContador
.Contador
ao invés de um *Contador
. Para resolver isso, é melhor criar um construtor que mostra aos usuários da nossa API que seria melhor ele mesmo não inicializar seu tipo.Contador
.Mutex
nos permite adicionar travas aos nossos dadosWaitGroup
é uma maneira de esperar as goroutines terminarem suas tarefasUm erro comum de um iniciante em Go é usar demais os channels e goroutines apenas porque é possível e/ou porque é divertido. Não tenha medo de usar umsync.Mutex
se for uma solução melhor para o seu problema. Go é pragmático em deixar você escolher as ferramentas que melhor resolvem o seu problema e não te força em um único estilo de código.
go vet
nos seus scripts de build porque ele pode te alertar a respeito de bugs mais sutis no seu código antes que eles atinjam seus pobres usuários.