Go Academy · Aula

Direção de canais e padrões de pipeline

Canais somente para leitura, somente para escrita e pipelines

Aula 4 de 412 etapas

Direção de canais e padrões de pipeline é uma aula grátis de Go Academy no CoddyKit. Esta é a aula 4 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.

Tipos de canais direcionais

Go permite restringir canais a somente envio ou somente recebimento nas assinaturas de tipos. Isso documenta a intenção e evita o uso incorreto:

package main

// send-only: can only send, not receive or close (close is allowed by sender)
func sender(out chan<- int) {
    out <- 42
}

// receive-only: can only receive, not send or close
func receiver(in <-chan int) int {
    return <-in
}

// bidirectional: can do both
func relay(in <-chan int, out chan<- int) {
    out <- <-in
}

Convertendo direções de canais

Um canal bidirecional pode ser convertido implicitamente para qualquer um dos tipos direcionais, mas o inverso não é possível:

package main
import "fmt"

func produce(out chan<- int) { out <- 1; close(out) }
func consume(in <-chan int)  { fmt.Println(<-in) }

func main() {
    ch := make(chan int)   // bidirectional
    go produce(ch)         // auto-converts to chan<- int
    consume(ch)            // auto-converts to <-chan int
    // chan<- int cannot be converted back to <-chan int
}

Canalização: etapa 1 — gerador

Uma canalização encadeia goroutines em que cada etapa lê do canal de saída da etapa anterior. O gerador é a primeira etapa:

package main
import "fmt"

func generate(nums ...int) <-chan int {
    out := make(chan int)
    go func() {
        for _, n := range nums {
            out <- n
        }
        close(out)
    }()
    return out
}

func main() {
    ch := generate(2, 3, 4, 5)
    for v := range ch { fmt.Println(v) }
}

Canalização: etapa 2 — transformação

As etapas intermediárias recebem de um canal, transformam os dados e enviam o resultado para outro:

package main
import "fmt"

func generate(nums ...int) <-chan int {
    out := make(chan int)
    go func() { for _, n := range nums { out <- n }; close(out) }()
    return out
}

func square(in <-chan int) <-chan int {
    out := make(chan int)
    go func() {
        for v := range in { out <- v * v }
        close(out)
    }()
    return out
}

func main() {
    for v := range square(generate(2, 3, 4, 5)) {
        fmt.Println(v)  // 4, 9, 16, 25
    }
}

Canalização: exemplo completo com três etapas

Encadeando três etapas — generate, transformar e filtrar:

package main
import "fmt"

func gen(nums ...int) <-chan int {
    c := make(chan int)
    go func() { for _, n := range nums { c <- n }; close(c) }()
    return c
}

func double(in <-chan int) <-chan int {
    c := make(chan int)
    go func() { for v := range in { c <- v * 2 }; close(c) }()
    return c
}

func evens(in <-chan int) <-chan int {
    c := make(chan int)
    go func() { for v := range in { if v%2 == 0 { c <- v } }; close(c) }()
    return c
}

func main() {
    for v := range evens(double(gen(1,2,3,4,5))) {
        fmt.Println(v)  // 2, 4, 6, 8, 10
    }
}

Cancelamento de canalização com o canal done

Passe um canal done para permitir que as etapas da canalização terminem antecipadamente quando forem canceladas:

package main
import "fmt"

func gen(done <-chan struct{}, nums ...int) <-chan int {
    out := make(chan int)
    go func() {
        defer close(out)
        for _, n := range nums {
            select {
            case out <- n:
            case <-done:  // cancel signal
                return
            }
        }
    }()
    return out
}

func main() {
    done := make(chan struct{})
    ch := gen(done, 1, 2, 3, 4, 5)
    fmt.Println(<-ch)  // 1
    close(done)        // cancel remaining work
    fmt.Println("pipeline cancelled")
}

Distribuição: dividindo o trabalho

A distribuição divide o trabalho de um canal entre várias goroutines para processamento paralelo:

package main
import ("fmt"; "sync")

func fanOut(in <-chan int, workers int) []<-chan int {
    outs := make([]<-chan int, workers)
    for i := 0; i < workers; i++ {
        out := make(chan int)
        outs[i] = out
        go func() {
            for v := range in { out <- v * v }  // each worker processes
            close(out)
        }()
    }
    return outs
}

func main() {
    fmt.Println("fan-out distributes work to multiple goroutines")
    _ = sync.WaitGroup{}
}

Concentração: mesclando canais

A convergência combina vários canais em um só:

package main
import ("fmt"; "sync")

func merge(cs ...<-chan int) <-chan int {
    out := make(chan int)
    var wg sync.WaitGroup
    for _, c := range cs {
        wg.Add(1)
        c := c
        go func() { defer wg.Done(); for v := range c { out <- v } }()
    }
    go func() { wg.Wait(); close(out) }()
    return out
}

func gen(nums ...int) <-chan int {
    c := make(chan int)
    go func() { for _, n := range nums { c <- n }; close(c) }()
    return c
}

func main() {
    for v := range merge(gen(1,2), gen(3,4), gen(5,6)) {
        fmt.Println(v)
    }
}

Boas práticas de fluxo

Princípios de projeto do fluxo:

  • Cada etapa: uma gorrotina lê de <-chan, grava em chan<- e fecha a saída quando termina
  • Somente o produtor fecha o canal — nunca o consumidor
  • Passe um canal done (ou um contexto) para permitir o cancelamento
  • Use tipos de canal direcionais em todas as assinaturas de função
  • Drene os canais ao cancelar para evitar vazamentos de gorrotinas

Fluxo do mundo real: processamento de CSV

Os fluxos são ideais para o processamento de dados — ler linhas, analisar, filtrar e transformar:

package main
import ("fmt"; "strings")

func splitLines(data string) <-chan string {
    out := make(chan string)
    go func() {
        for _, line := range strings.Split(data, "\n") {
            if line != "" { out <- line }
        }
        close(out)
    }()
    return out
}

func main() {
    csv := "alice,30\nbob,25\ncarol,35"
    for line := range splitLines(csv) {
        parts := strings.Split(line, ",")
        fmt.Printf("name=%s age=%s\n", parts[0], parts[1])
    }
}

Verificação rápida

Qual é a finalidade dos tipos de canal direcionais nas assinaturas de função?

Recapitulação: direção de canais e fluxos

Resumo:

  • chan<- T somente para envio, <-chan T somente para recebimento — intenção documentada e segurança em tempo de compilação
  • Fluxos: encadeiam gorrotinas, cada uma lendo de um canal e gravando em outro
  • Distribuição: um canal de entrada → várias gorrotinas
  • Convergência: vários canais → combinados em um só
  • Sempre feche os canais pelo lado do remetente; use um canal de conclusão para o cancelamento
Grátis para começar

Aprenda Go com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
51
Aulas
203

Perguntas Frequentes

A aula “Direção de canais e padrões de pipeline” é grátis?

Sim — o texto completo de “Direção de canais e padrões de pipeline” é 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 “Direção de canais e padrões de pipeline”?

Canais somente para leitura, somente para escrita e pipelines 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 4 de 4.

Quanto tempo leva a aula “Direção de canais e padrões de pipeline”?

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.

Todas as aulas deste curso

  1. Iniciando goroutines
  2. Canais sem buffer
  3. Canais com buffer
  4. Direção de canais e padrões de pipeline
← Voltar para Go Academy