0Pricing
Go Academy · Lekcja

Fan-Out i Fan-In

Rozdzielaj i zbieraj pracę

Fan-Out i Fan-In to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.

Fan-out i fan-in

Fan-out oznacza uruchomienie kilku goroutines odczytujących dane z jednego kanału i rozdzielających pracę. Fan-in oznacza połączenie wyników kilku goroutines z powrotem w jeden kanał.

  • Fan-out rozkłada obciążenie między workerów
  • Fan-in konsoliduje wyniki na potrzeby odbiorcy

Etap generatora

Potok rozpoczyna się od generatora — funkcji, która zwraca kanał, przesyła do niego wartości z własnej goroutine, a następnie go zamyka.

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

Fan-out

Aby zastosować fan-out, należy uruchomić kilka goroutines odczytujących dane z tego samego kanału wejściowego. Każda z nich wykonuje tę samą funkcję przetwarzającą i tworzy własny kanał wyjściowy.

in := gen(1, 2, 3, 4, 5)
c1 := square(in)
c2 := square(in)

Etap przetwarzania

Etap square odczytuje dane z in, podnosi każdą wartość do kwadratu i wysyła ją do nowego kanału wyjściowego. Wiele instancji tego etapu współdzieli jedno wejście.

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

Fan-in za pomocą merge

Fan-in łączy kilka kanałów w jeden. Obiekt sync.WaitGroup śledzi goroutines obsługujące poszczególne kanały, a goroutine zamykająca czeka na zakończenie wszystkich z nich, zanim zamknie połączone wyjście.

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

Dlaczego WaitGroup

Każda goroutine łącząca kanały kopiuje dane z jednego kanału wejściowego do out. Nie wolno zamknąć out, dopóki wszystkie kanały wejściowe nie zostaną opróżnione. WaitGroup zlicza aktywne goroutines kopiujące dane, a goroutine zamykająca blokuje się na wg.Wait() do czasu ich zakończenia.

Przechwytywanie zmiennej pętli

W starszych wersjach Go zamknięcie musi przyjmować c jako parametr, aby każda goroutine powiązała własny kanał, a nie współdzieloną zmienną pętli. Jawne przekazanie c pozwala uniknąć klasycznego błędu zmiennej pętli.

Kompletny fan-out i fan-in

Ten program generuje liczby, rozdziela je do dwóch etapów square, a następnie łączy wyniki i oblicza ich sumę.

package main

import (
    "fmt"
    "sync"
)

func gen(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 n := range in { out <- n * n }; close(out) }()
    return out
}

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

func main() {
    in := gen(1, 2, 3, 4, 5)
    c1 := square(in)
    c2 := square(in)
    total := 0
    for n := range merge(c1, c2) {
        total += n
    }
    fmt.Println("sum of squares:", total)
}

Kolejność nie jest gwarantowana

Ponieważ dwa etapy square rywalizują o te same dane wejściowe, kolejność elementów na połączonym wyjściu jest niedeterministyczna. Jeśli kolejność ma znaczenie, należy dołączyć do każdego elementu indeks albo użyć jednego etapu.

Kiedy stosować fan-out

Fan-out należy stosować, gdy dany etap jest wąskim gardłem, a jego praca może przebiegać równolegle. Jeśli generator nadrzędny działa wolno, dodanie kolejnych workerów podrzędnych nie pomoże — będą one po prostu bezczynnie czekać.

Backpressure

Niebuforowane kanały zapewniają naturalny mechanizm backpressure: szybki etap blokuje się, gdy wolny odbiorca nie nadąża. Zapobiega to nieograniczonemu wzrostowi zużycia pamięci w całym potoku.

Szybki test

Proszę sprawdzić zrozumienie fan-in.

Podsumowanie

Poznali Państwo fan-out i fan-in:

  • Fan-out: wiele goroutines odczytuje dane z jednego kanału
  • Fan-in: połączenie wielu kanałów w jeden za pomocą WaitGroup
  • Kolejność nie jest zachowywana w równoległych etapach
  • Niebuforowane kanały zapewniają backpressure

Często zadawane pytania

Czy lekcja „Fan-Out i Fan-In” jest bezpłatna?

Tak — pełny tekst „Fan-Out i Fan-In” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Fan-Out i Fan-In”?

Rozdzielaj i zbieraj pracę Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Go Academy?

Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Fan-Out i Fan-In”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?

Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Wzorzec puli workerów
  2. Fan-Out i Fan-In
  3. Etapy potoku
  4. Kontrolowane zamykanie
← Powrót do Go Academy