Чому неможливо отримати значення, що повертається, із програми, що присвоює її змінній?
Запуск goroutine (асинхронно) та отримання поверненого значення з функції є по суті суперечливими діями. Коли ви говорите, go
ви маєте на увазі "робіть це асинхронно" або навіть простіше: "Продовжуйте! Не чекайте завершення виконання функції". Але коли ви призначаєте функцію, що повертає значення змінної, ви очікуєте, що це значення буде в змінній. Отже, коли ви робите це, x := go doSomething(arg)
ви говорите: "Продовжуйте, не чекайте функції! Чекайте-чекайте-чекайте! Мені потрібно, щоб повернене значення було доступне у x
var прямо в наступному рядку нижче!"
Канали
Найбільш природний спосіб отримати значення з горутини - це канали. Канали - це труби, які з'єднують одночасно горутини. Ви можете надсилати значення в канали з однієї програми та отримувати ці значення в іншу програму або в синхронній функції. Ви можете легко отримати значення з програми, що не порушує паралелізм, використовуючи 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)
}
}
}
Приклад взято з Go By Example
CSP і передача повідомлень
Go в більшій мірі базується на теорії CSP . Наївний опис зверху можна було б точно окреслити з точки зору CSP (хоча я вважаю, що це виходить за межі питання). Я настійно рекомендую ознайомитися з теорією CSP хоча б тому, що це RAD. Ці короткі цитати дають напрямок мислення:
Як випливає з назви, CSP дозволяє описувати системи з точки зору компонентних процесів, які працюють незалежно та взаємодіють між собою виключно за допомогою передачі повідомлень .
В інформатиці передача повідомлень надсилає повідомлення процесу і покладається на процес та підтримуючу інфраструктуру для вибору та виклику фактичного коду для запуску. Передача повідомлень відрізняється від звичайного програмування, коли процес, підпрограма або функція викликається безпосередньо за іменем.