Canais sem buffer
Transferência síncrona entre goroutines
Canais sem buffer é uma aula grátis de Go Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Go Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Go Academy inclui 4 aulas no total.
O que é um canal?
Um canal é um meio tipado de comunicação entre goroutines. Os canais seguem o princípio do Go: Não se comunique compartilhando memória; compartilhe memória comunicando-se.
package main
import "fmt"
func main() {
ch := make(chan int) // unbuffered int channel
go func() {
ch <- 42 // send: blocks until someone receives
}()
v := <-ch // receive: blocks until someone sends
fmt.Println(v) // 42
}Semântica de canais sem buffer
Um canal sem buffer não tem capacidade. Um envio fica bloqueado até que um receptor esteja pronto, e um recebimento fica bloqueado até que um remetente envie. Isso garante uma transferência síncrona:
package main
import "fmt"
func double(in <-chan int, out chan<- int) {
for v := range in {
out <- v * 2
}
close(out)
}
func main() {
in := make(chan int)
out := make(chan int)
go double(in, out)
go func() { in <- 3; in <- 5; close(in) }()
for v := range out { fmt.Println(v) }
// 6
// 10
}Canal como mecanismo de sincronização
Canais sem buffer sincronizam goroutines — use-os como sinal de que o trabalho terminou:
package main
import "fmt"
func compute(result chan<- int) {
sum := 0
for i := 1; i <= 100; i++ { sum += i }
result <- sum
}
func main() {
ch := make(chan int)
go compute(ch)
fmt.Println("Result:", <-ch) // blocks until compute sends
}Fechando um canal
O sender fecha um canal com close(ch) para sinalizar que nenhum valor adicional será enviado. Receivers detectam o fechamento usando a forma de dois valores:
package main
import "fmt"
func generate(ch chan<- int, max int) {
for i := 0; i < max; i++ {
ch <- i
}
close(ch) // signal done
}
func main() {
ch := make(chan int)
go generate(ch, 5)
for v := range ch { // range detects close automatically
fmt.Println(v)
}
fmt.Println("channel closed")
}Recebimento de dois valores
O recebimento de dois valores v, ok := <-ch informa se o canal ainda está aberto:
package main
import "fmt"
func main() {
ch := make(chan string, 1)
ch <- "hello"
close(ch)
v1, ok1 := <-ch
fmt.Println(v1, ok1) // hello true
v2, ok2 := <-ch
fmt.Println(v2, ok2) // "" false — channel closed
}Enviar para um canal fechado causa pânico
Enviar para um canal fechado causa pânico. Somente o sender deve fechar um canal — nunca o receiver:
package main
import "fmt"
func main() {
ch := make(chan int)
close(ch)
// Receiving from closed channel returns zero value
v, ok := <-ch
fmt.Println(v, ok) // 0 false
// Sending to closed channel panics:
defer func() { recover() }()
ch <- 1 // panic: send on closed channel
}Canais direcionais
Restrinja canais a somente envio (chan<- T) ou somente recebimento (<-chan T) nas assinaturas de função, para obter clareza e segurança:
package main
import "fmt"
func producer(out chan<- int) { // send-only
for i := 0; i < 3; i++ { out <- i }
close(out)
}
func consumer(in <-chan int) { // receive-only
for v := range in { fmt.Println(v) }
}
func main() {
ch := make(chan int)
go producer(ch)
consumer(ch)
}Pingue-pongue entre goroutines e canais
Duas goroutines passam uma mensagem de um lado para o outro por meio de canais — uma demonstração clássica de sincronização:
package main
import "fmt"
func ping(ping, pong chan struct{}) {
for i := 0; i < 3; i++ {
<-ping
fmt.Println("ping")
pong <- struct{}{}
}
}
func main() {
ping := make(chan struct{})
pong := make(chan struct{})
go func() { for { <-pong; fmt.Println("pong"); ping <- struct{}{} } }()
go func() { for i := 0; i < 3; i++ { ping <- struct{}{}; <-pong } }()
// Simplified version:
fmt.Println("channels enable structured communication")
}Canais nil bloqueiam para sempre
Receber de um canal nil ou enviar para ele bloqueia para sempre. Às vezes, isso é usado intencionalmente em instruções select:
package main
import "fmt"
func main() {
var ch chan int // nil channel
fmt.Println(ch == nil) // true
// select with nil channel — that case is never selected
active := make(chan int, 1)
active <- 42
select {
case v := <-ch: // never selected (nil)
fmt.Println(v)
case v := <-active: // selected
fmt.Println("got:", v)
}
}Quando usar canais sem buffer
Use canais sem buffer quando:
- Precisar de uma transferência síncrona garantida
- A goroutine precisar confirmar o recebimento antes que o sender continue
- Estiver implementando semáforos ou contrapressão
- Estiver implementando canalizações em que cada etapa deve processar um item por vez
Verificação rápida
O que acontece quando se envia por um canal sem buffer sem que haja um receptor pronto?
Revisão: canais sem buffer
Resumo:
- Crie com
make(chan T)— capacidade zero - O envio fica bloqueado até que um receptor esteja pronto; o recebimento fica bloqueado até que um sender envie
- Somente o sender deve fechar um canal
range chitera até o fechamento- Recebimento de dois valores:
v, ok := <-ch - Use tipos direcionais para obter clareza:
chan<-e<-chan
Perguntas Frequentes
A aula “Canais sem buffer” é grátis?
Sim — o texto completo de “Canais sem buffer” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Go Academy, atualize para CoddyKit PRO. O curso de Go Academy inclui 4 aulas no total.
O que vou aprender em “Canais sem buffer”?
Transferência síncrona entre goroutines Você pratica Go Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Go Academy?
Nenhuma experiência prévia é necessária. Go Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Canais sem buffer”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Go Academy?
Sim. Cada aula de Go Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.