Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Context package

Context package

Avatar for Timo Savola

Timo Savola

January 18, 2017
Tweet

More Decks by Timo Savola

Other Decks in Programming

Transcript

  1. History golang.org/x/net/context package released in 2014 Developed for Google's needs

    context package in standard library since Go 1.7 Wider support in Go 1.8 (scheduled to be released in two weeks)
  2. Characteristics To be used with blocking calls Immutable: only way

    to modify a context is to derive a sub-context Hierarchical: operations on a high-level context trickle down to derived contexts Standard glue between various APIs, or candidate for such
  3. Deadlines Go already had I/O deadline APIs and timer channels

    Context is a generic mechanism Context combines layers of deadline configurations
  4. Cancellation Could be accomplished with plain channels etc. Context hides

    complexity caused by nesting Go APIs haven't traditionally given much thought to graceful shutdown Context promotes cancellation awareness, thanks to the common API Benefits architecture of non-trivial apps which are not expected to run forever
  5. Values Values stored in a context transit the call stack

    transparently Strong decoupling thanks to lexically scoped keys Solves similar problems as thread-local storage Request-scoped storage Not specific to a thread or a goroutine
  6. Building blocks Context interface and factory functions Convention: pass context

    as first function argument func Foo(ctx context.Context, ...)
  7. Example: Top level func main() { ctx := context.Background() //

    No timeout, cancellation, or values app(ctx) }
  8. 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() }
  9. 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 }
  10. 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 } }
  11. API implementation support Context.Done() channel will be closed on deadline

    or cancellation A channel may be read concurrently A closed channel may be read repeatedly Context.Deadline() value may be used with readers/writers, but it doesn't respect cancellation
  12. 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) ...
  13. 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
  14. Thoughts Simple, but high-impact if supported widely Violates the single

    responsibility principle... by definition Value API's role is unclear, and controversial