Dlaczego nie można pobrać wartości zwracanej z gorutyny przypisującej ją do zmiennej?
Uruchamianie goroutine (asynchronicznie) i pobieranie wartości zwracanej z funkcji są zasadniczo sprzecznymi akcjami. Kiedy mówisz, że go
masz na myśli „rób to asynchronicznie” lub nawet prościej: „Dalej! Nie czekaj na zakończenie wykonywania funkcji”. Ale kiedy przypiszesz wartość zwracaną przez funkcję do zmiennej, spodziewasz się, że ta wartość będzie znajdować się w zmiennej. Więc kiedy to zrobisz, x := go doSomething(arg)
mówisz: "Dalej, nie czekaj na funkcję! Czekaj-czekaj-czekaj! Potrzebuję, aby zwrócona wartość była dostępna w x
var bezpośrednio w następnym wierszu poniżej!"
Kanały
Najbardziej naturalnym sposobem uzyskania wartości z gorutyny są kanały. Kanały to rury, które łączą równoległe gorutyny. Możesz wysyłać wartości do kanałów z jednej gorutyny i odbierać te wartości do innej gorutyny lub w funkcji synchronicznej. Możesz łatwo uzyskać wartość z gorutyny, która nie przerywa współbieżności, używając select
:
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
time.Sleep(time.Second * 1)
c1 <- "one"
}()
go func() {
time.Sleep(time.Second * 2)
c2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
}
Przykład pochodzi z Go By Example
CSP i przekazywanie wiadomości
Go jest w dużej mierze oparty na teorii CSP . Naiwny opis z powyższego mógłby być precyzyjnie zarysowany w kontekście CSP (chociaż uważam, że nie wchodzi w zakres pytania). Zdecydowanie zalecam zapoznanie się z teorią CSP, przynajmniej dlatego, że jest to RAD. Te krótkie cytaty dają kierunek myślenia:
Jak sama nazwa wskazuje, CSP umożliwia opis systemów w kategoriach procesów składowych, które działają niezależnie i współdziałają ze sobą wyłącznie poprzez komunikację z przekazywaniem wiadomości .
W informatyce przekazywanie wiadomości wysyła wiadomość do procesu i opiera się na procesie oraz infrastrukturze pomocniczej w celu wybrania i wywołania właściwego kodu do uruchomienia. Przekazywanie komunikatów różni się od konwencjonalnego programowania, w którym proces, podprogram lub funkcja jest bezpośrednio wywoływana przez nazwę.