Stavo seguendo il Go Tour e sono un po 'bloccato quando si tratta di goroutine. Capisco che sono molto leggeri e che ogni volta che un blocchi goroutine, un altro comincerò ma non riesco a ottenere la mia testa intorno a come questo esempio funziona realmente:Come funzionano le goroutine?
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(1000 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
Capisco che un goroutine viene avviato per la funzione say con l'argomento "world", ma per quanto ho capito dovrebbe stampare "world" cinque volte e "ciao" una volta. Tuttavia non capisco il motivo per cui l'uscita è come è:
hello
world
hello
world
hello
world
hello
world
hello
Dalla mia comprensione limitata di fili da altre lingue l'uscita dovrebbe essere stato qualcosa di simile:
hello
world
world
world
world
world
o come questo:
world
world
world
hello
world
world
Perché la seconda riga viene eseguita anche cinque volte? Qualcosa sotto l'istruzione go
classifica come parte della routine go?
Anche la diapositiva successiva mostra qualcosa che non posso ottenere la mia testa rotonda di nuovo:
package main
import "fmt"
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // send sum to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
Un goroutine viene avviato per la seconda metà della fetta e poi un altro per la prima parte della sezione, tuttavia i valori x
e sono stati assegnati a due valori diversi. Per come la vedo io, la funzione sum
invierà la somma al canale c
e quindi il prossimo sum
invierà la somma allo stesso canale c
, quindi come possono essere assegnate alle due variabili due valori diversi? Il canale c
non dovrebbe contenere un solo valore sum
?
Apprezzo che questa è una domanda piuttosto lunga, ma non sono riuscito a trovare la risposta a queste domande.
Oh. Penso di aver capito. Il principale è di per sé una routine di go come hai detto tu. Il saluto viene stampato perché il principale viene bloccato dal sonno all'interno della routine di go. Perché ogni volta che una routine viene bloccata, una nuova avvia le ripetizioni principali per 5 volte, ma allo stesso tempo la funzione si ripete 5 volte. Hello viene stampato per primo perché il codice salta sopra la routine in attesa che si addormenti. – Bula
Anche questa è un'altra domanda riguardante il mio secondo esempio. Diciamo che ci sono milioni di chiamate per le funzioni di somma con il go preposto ad esso. Se il programma non arriva alla linea che blocca il programma prima che la somma finisca di calcolare, quel valore andrebbe perso proprio? – Bula
@Bula scusa per la risposta in ritardo. Sì, main() è una goroutine di per sé, e produrrà in 'Sleep()'. – VonC