0Pricing
Go Academy · Lezione

Direzione dei canali e modelli pipeline

Canali in sola lettura, in sola scrittura e pipeline

Direzione dei canali e modelli pipeline è una lezione Go Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Go Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Go Academy include 4 lezioni in totale.

Tipi di canale unidirezionali

Go consente di limitare i canali alla sola trasmissione o alla sola ricezione nelle firme dei tipi. In questo modo documenta l'intento e previene gli utilizzi errati:

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
}

Conversione delle direzioni dei canali

Un canale bidirezionale può essere convertito implicitamente in uno dei due tipi unidirezionali, ma non è possibile il contrario:

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
}

Pipeline: fase 1 — Generatore

Una pipeline concatena goroutine in cui ogni fase legge dal canale di output della fase precedente. Il generatore è la prima fase:

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) }
}

Pipeline: fase 2 — Trasformazione

Le fasi intermedie ricevono da un canale, trasformano i dati e li inviano a un altro canale:

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
    }
}

Pipeline: esempio completo in tre fasi

Concatenamento di tre fasi: generazione, trasformazione e filtraggio:

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
    }
}

Annullamento della pipeline con il canale done

Passi un canale done per consentire alle fasi della pipeline di terminare anticipatamente quando viene richiesto l'annullamento:

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")
}

Fan-out: distribuzione del lavoro

Il fan-out distribuisce il lavoro proveniente da un canale a più goroutine per l'elaborazione parallela:

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{}
}

Fan-in: unione dei canali

Fan-in unisce più canali in uno solo:

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)
    }
}

Buone pratiche per le pipeline

Principi di progettazione delle pipeline:

  • Ogni fase: la goroutine legge da <-chan, scrive su chan<- e chiude l'output al termine
  • Solo il produttore chiude il canale, mai il consumatore
  • Passi un canale done (o un contesto) per l'annullamento
  • Usi tipi di canale direzionali in tutte le firme delle funzioni
  • Svuoti i canali quando annulli l'operazione per evitare perdite di goroutine

Pipeline nel mondo reale: elaborazione di CSV

Le pipeline sono particolarmente efficaci nell'elaborazione dei dati: leggono le righe, le analizzano, le filtrano e le trasformano:

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 rapida

Qual è lo scopo dei tipi di canale direzionali nelle firme delle funzioni?

Riepilogo: direzione dei canali e pipeline

Riepilogo:

  • chan<- T è di sola scrittura, <-chan T è di sola lettura: documentazione dell'intento e sicurezza verificata in fase di compilazione
  • Pipeline: concatenano goroutine, ognuna delle quali legge da un canale e scrive su un altro
  • Fan-out: un canale di input → più goroutine
  • Fan-in: più canali → un unico canale unificato
  • Chiuda sempre i canali dal lato del mittente; usi un canale done per l'annullamento

Domande Frequenti

La lezione «Direzione dei canali e modelli pipeline» è gratuita?

Sì — il testo completo di «Direzione dei canali e modelli pipeline» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Go Academy, passa a CoddyKit PRO. Il corso Go Academy include 4 lezioni in totale.

Cosa imparerò in «Direzione dei canali e modelli pipeline»?

Canali in sola lettura, in sola scrittura e pipeline Eserciti Go Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Go Academy?

Non è richiesta alcuna esperienza precedente. Go Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Direzione dei canali e modelli pipeline»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Go Academy?

Sì. Ogni lezione Go Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Avviare goroutine
  2. Canali non bufferizzati
  3. Canali bufferizzati
  4. Direzione dei canali e modelli pipeline
← Torna a Go Academy