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.

Reply via email to