Mam ochotę na odpowiedź na moje pytanie, to nie pytanie o pewność, ponieważ zacząłem grać tylko z wyjazdem przez kilka dni. Czy powinniśmy zawiesić zadania związane z IO (jak prośby HTTP) w Goutines, nawet jeśli miało być użyte w sekwencyjnym przypadku użycia?

Oto mój naiwny przykład. Powiedzmy, że mam metodę, która tworzy 3 żądania HTTP, ale należy wykonać sekwencyjnie. Czy istnieje jakaś korzyści w tworzeniu metod invoke jako moutines? Rozumiem, że poniższy przykład rzeczywiście wyeliminowałby.

func myMethod() {
   chan1 := make(chan int)
   chan2 := make(chan int)
   chan3 := make(chan int)

   go invoke1(chan1)

   res1 := <-chan1
   invoke2(res1, chan2)

   res2 := <-chan2
   invoke3(res2, chan3)

   // Do something with <-chan3
}

Jeden możliwy powód, który przychodzi na myśl, jest przyszłe metody invoke, gdy są one wywoływane w jednoczesnym kontekście później, gdy inne opracowanie rozpocznie się ponowne wykorzystanie metody. Jakieś inne powody?

0
n00b 10 luty 2018, 14:36

3 odpowiedzi

Jestem trochę późno na imprezę, ale myślę, że wciąż mam coś do dzielenia się.

Przed odpowiedzią na pytanie, chciałbym nurkować trochę do przysłówki, współbieżność nie jest parelizmu . Jest to bardzo powszechne nieporozumienie języka Gooutine i GO's Język, że gdy ludzie myślą o moutine, myśli o zdolności paleń.

Ale gdy Rob Pike wskazał w wielu rozmowach, co zapewnia płynność i gnoutina, jest zgodna. Concentenencja jest modelem lepszego wspierania rzeczywistego świata, sposób i struktury kodu, w jaki sposób kod w interakcji .

Więc wróć do pytania. Czy Gooutine należy użyć, gdy kroki są sekwencyjne? To zależy od projektu. Jeśli twój kod tworzy poszczególne części, które mówi się ze sobą bardzo naturalnie, lub jeśli niektóre z kodeksu zachowuje stan i często return po prostu nie ma sensu lub jeśli twój kod pasuje do każdego innego projektu konkurencji, to jest Idealnie dobrze, aby użyć montażu i kanału i select. Robić Rob Pike, ponownie daje rozmowę o LEXER używanym przez teraz text/template, gdzie Lexer używa gooutine, ale najwyraźniej korzystanie z LEXER, używaj sekwencyjnie Lexer. Stwierdził, że za pomocą Gooutine and Channel, kosztem małego występu, lepszy interfejs API jest osiągnięty.

Ale z drugiej strony, w swoim przykładzie i prawdopodobnie o tym, o czym myślisz (kody, które mogą wymagać przyszłego parelizmu), zgadzam się z @marc. Trzymaj się połączenia blokującego, przynajmniej na razie.

2
leaf bebop 13 luty 2018, 06:09

Możesz użyć kanału taka jak BUF lub użyj [] ciągów (plasterka adresów URL). Nie masz żadnych korzyści z Gorutunines, jeśli potrzebujesz tylko sekwencyjnej egzekucji, ponieważ nie mogliśmy kontrolować Gooutine, gdy zaczyna się.

Ale możemy zapytać, nie czekaj runtime.Gosched()

Z Dokumentacji: Gosched Daje procesor, umożliwiając uruchomienie innych guzin. Nie zawiesia obecnej gorynosy, więc wykonanie wznawia się automatycznie.

Przykład wykonania sekwencyjnego:

package main

func main() {
    urls := []string{
        "https://google.com",
        "https://yahoo.com",
        "https://youtube.com",
    }
    buf := make([][]byte, 0, len(urls))
    for _, v := range urls {
        buf = append(buf, sendRequest(v))
    }
}

func sendRequest(url string) []byte {
    //send
    return []byte("")
}
0
Igor Khristenko 10 luty 2018, 13:27

Dla rozwiązania jako takiego nie widzę żadnego zysku, rozwiązując problem tak, jak jesteś w świecie rzeczywistym. To nie znaczy, że nie ma zysku w twoim rozwiązaniu. Jeśli jesteś po praktyce, na przykład synchronizując procedury Go, masz mnóstwo możliwości eksperymentowania i uczenia się.

Więc do mnie jest daleko od jasnego nie, ale nie ma jasności tak. Powstałbym od powiedzenia, może to zależy od tego, co dokładnie twój po. Czy jesteś po rozwiązaniu problemu lub uczenia się?

-1
Patrik Iselind 10 luty 2018, 16:49