Context package

at Helsinki Gophers meetup

18 January 2017

Timo Savola

CTO, Ninchat

History

Three jobs

Characteristics

Deadlines

Cancellation

Values

Building blocks

func Foo(ctx context.Context, ...)

Example: Top level

func main() {
    ctx := context.Background() // No timeout, cancellation, or values

    app(ctx)
}

Example: Reacting to events

func app(ctx context.Context) {
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()

    go waitForSignalAndInvoke(os.Interrupt, cancel)

    doStuff(ctx)
}

func waitForSignalAndInvoke(number os.Signal, cancel context.CancelFunc) {
    c := make(chan os.Signal)
    signal.Notify(c, number)
    <-c
    cancel()
}

Example: API call with a deadline

func doStuff(ctx context.Context) (err error) {
    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
    defer cancel()

    result, err := api.PerformOperation(ctx, 10, 20)
    if err != nil {
        return
    }

    fmt.Println(result)
    return
}

Example: Implementation of a blocking API

func PerformOperation(ctx context.Context, x, y int) (result int, err error) {
    performance := startPerforming(x, y)

    select {
    case result, _ = <-performance.resultChannel:
        return

    case <-ctx.Done(): // Timed out or cancelled?
        err = ctx.Err()
        performance.abort()
        return
    }
}

API implementation support

Supported by net package

since 1.7:

Dialer.DialContext(ctx context.Context, net, addr string) (Conn, error)

since 1.8:

Resolver.LookupAddr(ctx context.Context, addr string) (names []string, err error)
Resolver.LookupCNAME(ctx context.Context, host string) (cname string, err error)
Resolver.LookupHost(ctx context.Context, host string) (addrs []string, err error)
...

Supported by net/http package

since 1.7:

Request.WithContext(ctx context.Context) *Request
Request.Context() context.Context
ServerContextKey
LocalAddrContextKey

since 1.8:

Server.Shutdown(ctx context.Context) error

Supported by os/exec package

since 1.7:

CommandContext(ctx context.Context, name string, arg ...string) *Cmd

Supported by database/sql package

since 1.8:

DB.QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)
...

Thoughts

Thank you

Timo Savola

CTO, Ninchat