logoalt Hacker News

the_gipsy01/21/20252 repliesview on HN

Consider this:

    ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
    reader := ioContextReader(ctx, r)
    ...
    ctx, cancel := context.WithTimeout(ctx, 1*time.Second)
    ctx = context.WithValue(ctx, "hello", "world")
    ...
    func(ctx context.Context) {
        reader.Read() // does not time out after one second, does not contain hello/world.
        ...
    }(ctx)

Replies

bheadmaster01/21/2025

There are two solutions, depending on your real use case:

1) You're calling Read() directly and don't need to use functions that strictly accept io.Reader - then just implement ReadContext:

    func (rc ioContextReader) ReadContext(ctx context.Context, p []byte) (n int, err error) {
        done := make(chan struct{})
        go func() {
            n, err = rc.Reader.Read(p)
            close(done)
        }()

        select {
        case <-ctx.Done():
            return 0, ctx.Err()
        case <-done:
            return n, err
        }
    }
Otherwise, just wrap the ioContextReader with another ioContextReader:

    reader = ioContextReader(ctx, r)
show 1 reply
rad_gruchalski01/22/2025

Of course not - you're not handling the context at all in the called function. What's there to consider, reader.Read() has no idea about your timeout and value store intent. How would it, telepathy?