Go foi projetado desde o início para facilitar a concorrência, tornando possível escrever código que executa várias tarefas ao mesmo tempo sem perder a cabeça. Neste artigo, vou te mostrar o que é concorrência, como funciona em Go e como você pode usar goroutines e channels para deixar seu código mais eficiente e responsivo.
Concorrência vs. Paralelismo: Qual é a Diferença?
Antes de tudo, vamos esclarecer um ponto: concorrência não é a mesma coisa que paralelismo.
- Concorrência: quando seu código lida com múltiplas tarefas ao mesmo tempo, alternando entre elas conforme necessário.
- Paralelismo: quando seu código executa várias tarefas ao mesmo tempo, literalmente ao mesmo tempo, geralmente em múltiplos núcleos de CPU.
Pensa assim: você está cozinhando um jantar. Enquanto a água ferve (uma tarefa), você pica os legumes (outra tarefa). Isso é concorrência. Agora, se você tivesse um clone seu picando os legumes enquanto você ferve a água, isso seria paralelismo.
Goroutines: Executando Funções Concorrentemente
Em Go, criar uma função concorrente é incrivelmente fácil. Basta colocar go
antes da chamada da função e pronto, ela roda em segundo plano sem te incomodar.
Exemplo simples de goroutine:
package main
import (
"fmt"
"time"
)
func digaOla() {
fmt.Println("Olá, mundo!")
}
func main() {
go digaOla() // Rodando a função como goroutine
time.Sleep(time.Second) // Esperando um pouco para ver a saída
}
Aqui, digaOla()
é executada de forma concorrente, mas como o programa principal pode terminar antes que ela rode, colocamos um time.Sleep(time.Second)
só pra garantir que dê tempo de ver a saída. Claro que, em código real, a gente usaria algo mais robusto, como channels, para sincronização.
Channels: Conversando Entre Goroutines
Goroutines são legais, mas como elas conversam entre si? Em Go, usamos channels, que funcionam como uma esteira de produção: uma goroutine coloca um dado de um lado e outra goroutine pega do outro.
Unbuffered Channels: Mensagens "Na Hora"
Os unbuffered channels são como passar um recado para um amigo pessoalmente: você fala e ele escuta na mesma hora.
package main
import "fmt"
func main() {
mensagens := make(chan string) // Criando um channel de strings
go func() {
mensagens <- "Olá, Go!"
}()
fmt.Println(<-mensagens) // Recebendo a mensagem do channel
}
Aqui, a goroutine anônima envia uma mensagem pelo channel, e a main
recebe e imprime. O channel bloqueia até que haja um receptor do outro lado, garantindo sincronização.
Buffered Channels: Guardando Mensagens
Buffered channels são como um correio: você pode colocar mensagens na caixa antes que o carteiro as retire.
package main
import "fmt"
func main() {
numeros := make(chan int, 3) // Criando um buffered channel com capacidade 3
numeros <- 1
numeros <- 2
numeros <- 3
fmt.Println(<-numeros) // 1
fmt.Println(<-numeros) // 2
fmt.Println(<-numeros) // 3
}
Aqui, o channel pode armazenar até 3 valores sem bloquear. Se tentarmos enviar um 4º valor antes de consumir algum, o programa trava até que haja espaço.
Select: Lidando com Múltiplos Channels
O comando select
em Go permite ouvir vários channels ao mesmo tempo, tipo um garçom atendendo várias mesas ao mesmo tempo.
package main
import (
"fmt"
"time"
)
func main() {
canal1 := make(chan string)
canal2 := make(chan string)
go func() {
time.Sleep(2 * time.Second)
canal1 <- "Mensagem do canal 1"
}()
go func() {
time.Sleep(1 * time.Second)
canal2 <- "Mensagem do canal 2"
}()
select {
case msg1 := <-canal1:
fmt.Println(msg1)
case msg2 := <-canal2:
fmt.Println(msg2)
}
}
Aqui, select
escolhe o primeiro channel que estiver pronto, garantindo que a resposta mais rápida seja processada primeiro.
Concorrência na Vida Real
Agora que você já viu como usar goroutines e channels, aqui estão alguns exemplos do mundo real onde a concorrência brilha:
- Servidores Web: Cada requisição é tratada em uma goroutine separada, evitando travamentos.
- Scrapers de Dados: Se você precisar buscar informações de vários sites, pode fazer isso concorrentemente e acelerar o processo.
- Jogos Multiplayer: Goroutines podem gerenciar o estado de cada jogador e enviar atualizações rapidamente.
Conclusão
Go torna a concorrência fácil e eficiente, permitindo criar aplicações escaláveis e responsivas sem dores de cabeça. Ao dominar goroutines, channels e select
, você consegue construir sistemas que aproveitam melhor o hardware e evitam travamentos.
Então, da próxima vez que precisar rodar várias coisas ao mesmo tempo, lembre-se: goroutines são seus amigos, e channels são a melhor forma de manter a conversa em ordem! 🚀
Top comments (0)