MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Transmiterea fluxurilor de date

Adesea, o gorutină transmite către o altă gorutină prin canal nu doar valori individuale, ci un anumit flux de date. În acest caz, algoritmul general constă în faptul că gorutina trimitătoare trimite date pe parcursul unei perioade de timp. Când datele de transmis se termină, trimitătorul închide canalul.

Gorutina receptor primește date din canal într-un ciclu infinit. Dacă este primit un semnal de închidere a canalului, atunci se iese din ciclul infinit.

package main
import "fmt"

func main(){
   intCh := make(chan int) 
    
   go factorial(7, intCh)
  
   for { 
         num, opened := <- intCh     // primim date din flux
         if !opened { 
               break    // dacă fluxul este închis, ieșim din ciclu
         } 
         fmt.Println(num)
   }
}

func factorial(n int, ch chan int){
    defer close(ch)
    result := 1
    for i := 1; i <= n; i++{
        result *= i
        ch <- result     // trimitem câte un număr
    }
}

În acest caz, funcția main și gorutina factorial interacționează prin canalul intCh. Funcția factorial calculează secvențial factorialele numerelor de la 1 la n. Toate valorile calculate sunt trimise în canal. La finalizarea funcției factorial, canalul este închis prin apelul defer close(ch).

În funcția main, datele trimise sunt extrase din canal într-un ciclu infinit. În același timp, se verifică dacă canalul este deschis. Dacă canalul este închis și, prin urmare, nu mai are rost să obținem date din el, se iese din ciclul infinit:

for { 
    num, opened := <- intCh 
    if !opened { 
        break
    } 
    fmt.Println(num)
}

Ieșirea în consolă a programului va fi:

1
2
6
24
120
720
5040

Când extragem valori din canal, putem utiliza aceeași formă de ciclu for care este aplicată pentru parcurgerea colecțiilor:

for variabilă := canal{
    //...........
}

De exemplu, să rescriem exemplul anterior:

package main
import "fmt"

func main(){
   intCh := make(chan int) 
    
   go factorial(7, intCh)
  
    for num := range intCh{
        fmt.Println(num)
    }
}

func factorial(n int, ch chan int){
    defer close(ch)
    result := 1
    for i := 1; i <= n; i++{
        result *= i
        ch <- result
    }
}

Când canalul va fi închis, ieșirea din ciclul for se va face automat.