Below is an example of code that does some work even after timeout. In a perfect world it would be simple "return FetchLinks(user)", but unfortunately 3rd-party service is unreliable, so we did some caching and timeouts.
The idea is as follows: User sends a request, we try to fetch data from a 3rd-party, if that fails or response doesn't come in 2 seconds, then we stop waiting and serve data from the local DB. If request takes longer than 2 secs, we don't want to throw it away, we still want to write its data into the local DB. ctx, cancel := context.WithTimeout(ctx, 2*time.Second) defer cancel() linksCh := make(chan []*Link) go func() { links, err := FetchLinks(user) if err != nil { logger.WithError(err).Error("fetch links error") cancel() return } select { case <-ctx.Done(): case linksCh <- links: } if err := SyncLinks(user, links); err != nil { logger.WithError(err).Error("sync links error") return } }() select { case l := <-linksCh: return l, nil case <-ctx.Done(): return nil, ctx.Err() } On Mon, Apr 3, 2023 at 6:44 AM Nigel Tao <nigel...@golang.org> wrote: > > I'm working on a multi-threaded C++ project. We have the equivalent of > Go's channels, and are considering whether we also need to implement > the equivalent of Go's select. > > Does anyone have interesting, non-trivial examples of a Go select > statement in real code? > > By non-trivial, I mean that a lot of the selects that I've seen have > exactly two cases, one of them doing "real work" and the other being > either (1) "default" or (2) a timeout/cancel channel (e.g. > ctx.Done()). > > In our C++ API, our channel send/recv methods already have > try_send/try_recv equivalents for (1) and a timeout/cancel mechanism > for (2). > > bcmills' "Rethinking Classical > Concurrency Patterns" > (https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view) > uses select to implement higher level ResourcePool / WorkerPool APIs > but select is arguably a private implementation detail. While it might > not be as beautiful under the hood, I think we can already present > similar APIs using C++'s std::counting_semaphore. > > r's "A Concurrent Window System" > (https://swtch.com/~rsc/thread/cws.pdf) discusses select'ing from > separate window, keyboard and mouse channels but this could arguably > instead be a single channel of heterogenous elements (e.g. in C++, a > std::variant). > > It's more interesting to select over both input and output channels, > and output channels may become "ready to communicate" without new > input. But again, it may be possible to work around that by downstream > actors sending "I'm ready to receive" events onto the upstream actor's > heterogenous input channel. > > The most interesting selects I have so far is the > golang.org/x/net/http2 source code, whose internals have a bit of a > learning curve. If anyone has other examples, please share. > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/CAOeFMNWBtuEci9oPUFNa0v0gDC%3DV6Xb0N05Jyxo%3DxN2ywJALGA%40mail.gmail.com. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAD%2BeXGSKFQvVHEc2CTZxmNPS16RyZ3zHbYX42nLNNmv1hw5%2BvA%40mail.gmail.com.