Jestem pewien, że wcześniej widziałem pytanie, ale nie mogę go teraz znaleźć.

Zasadniczo chcę select na zablokowanym połączeniu, a także kanał.

Wiem, że mogę nacisnąć zablokowany wezwanie do gorynoszy i poczekaj na wynik przez kanał, jednak odczuwa to niewłaściwe rozwiązanie.

Czy istnieje idiomatyczny sposób na napisanie tego, którego brakuje?

Optymalnie byłoby coś w rodzaju:

select {
case a <- c:
  ...
case ans := connection.Read():
  ...
}
3
Cjen1 4 wrzesień 2020, 14:05

1 odpowiedź

Najlepsza odpowiedź

Jeśli masz kanał i funkcję, z której chcesz select, używając gooutine i kanału jest roztworem idiomatycznym. Zauważ, że jeśli wartość zostanie odebrana z kanału, to nie wpłynie na funkcję i będzie nadal działać. Możesz użyć context.Context, aby zasygnalizować jego wynik nie jest już potrzebny i może zakończyć się wcześnie.

Jeśli pozwolono mi odmówić, możesz "zrobić" funkcję wysłać na tym samym kanale, więc wystarczy otrzymać tylko z jednego kanału.

Inny pomysł refaktoryczny byłby dla funkcji do monitorowania tego samego kanału i powrotu wcześnie, więc możesz po prostu wykonać pojedyncze połączenie bez {x0}}.

Należy pamiętać, że jeśli chcesz to zrobić w wielu miejscach, możesz utworzyć funkcję pomocnika, aby uruchomić go asynchronicznie:

func launch(f func()) <-chan struct{} {
    done := make(chan struct{})
    go func() {
        defer close(done)
        f()
    }()
    return done
}

Przykładowa funkcja:

func test() {
    time.Sleep(time.Second)
}

A następnie używając go:

select {
case a := <-c:
    fmt.Println("received from channel:", a)
case <-launch(test):
    fmt.Println("test() finished")

}

Wypróbuj go na GO Plac zabaw.

4
icza 4 wrzesień 2020, 11:34