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

context.Context is not just for cancelation

context.Context is not just for cancelation

Masayuki Izumi

July 26, 2018
Tweet

More Decks by Masayuki Izumi

Other Decks in Programming

Transcript

  1. izumin5210 Engineer at Wantedly, Inc. Wantedly People ‣ Web Application

    Engineer - Server-side : Golang, Ruby, etc. - Web Frontend ‣ Interests in developer productivity on microservices ‣ I'll talk on builderscon Tokyo 2018 :)
  2. * https://golang.org/pkg/context/ Package context defines the Context type, which carries

    deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.* context.Context
  3. * https://golang.org/pkg/context/ Package context defines the Context type, which carries

    deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.* context.Context
  4. * https://golang.org/pkg/context/ Package context defines the Context type, which carries

    deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.* context.Context
  5. &/%

  6. &/%

  7. * https://golang.org/pkg/context/ Package context defines the Context type, which carries

    deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.* context.Context
  8. ͳΜͰ΋͸͍ͬͯศརʢʁʣ ctx := context.TODO() ctx = context.WithValue(ctx, "ctxkey1", 100) ctx

    = context.WithValue(ctx, "ctxkey2", "foobar") // Output: // 100 foobar fmt.Println(ctx.Value("ctxkey1"), ctx.Value("ctxkey2"))
  9. TFUUFSHFUUFSͰʢ͋Δఔ౓ʣܕΛकΖ͏ func GetFoo(ctx context.Context) string { if v, ok :=

    ctx.Value("foo").(string); ok { return v } return "" } func SetFoo(ctx context.Context, v string) context.Context { return context.WithValue(ctx, "foo", v) }
  10. func GetFoo(ctx context.Context) string { if v, ok := ctx.Value("foo").(string);

    ok { return v } return "" } func SetFoo(ctx context.Context, v string) context.Context { return context.WithValue(ctx, "foo", v) }
  11. type ctxKeyFoo struct {} func GetFoo(ctx context.Context) string { if

    v, ok := ctx.Value(ctxKeyFoo{}).(string); ok { return v } return "" } func SetFoo(ctx context.Context, v string) context.Context { return context.WithValue(ctx, ctxKeyFoo{}, v) } LFZͷॏෳΛ๷͝͏
  12. ! Bad pattern " ϩδοΫʢυϝΠϯ ӬଓԽϩδοΫʣʹؔΘΔ΋ͷΛೖΕͳ͍ type PostStore interface {

    Create(ctx context.Context) error } func (s *postStoreImpl) Create(ctx context.Context) error { title := GetPostTitleFromContext(ctx) body := GetPostBodyFromContext(ctx) // snip. }
  13. ! Bad pattern " JOUFSGBDFఆ͚ٛͩͰ͸ύϥϝλʹԿ͕ඞཁ͔Θ͔Βͳ͍DBMMFS͕಺෦࣮૷ʹґଘͯ͠͠·͏ type PostStore interface { Create(ctx

    context.Context) error } func (s *postStoreImpl) Create(ctx context.Context) error { title := GetPostTitleFromContext(ctx) body := GetPostBodyFromContext(ctx) // snip. }
  14. e.g. New Relic `context.Context` ʹ `newrelic.Transaction` Λ֨ೲ͓ͯ͘͠ ʢNJEEMFXBSF `http.Handler` ΍H31$ͷJOUFSDFQUPSͰ΍Ε͹0,ʣ

    // SetTransaction stores newrelic transaction object into given context. func SetTransaction(ctx context.Context, txn newrelic.Transaction) context.Context { return context.WithValue(ctx, txnKey, txn) } https://godoc.org/github.com/izumin5210/newrelic-contrib-go/nrutil
  15. e.g. New Relic + DB `sql.DB` ΛXSBQͯ͠ɼDPOUFYU͔Β5SBOTBDUJPOΛऔΓग़͠TFHNFOUΛ࡞Δ func (w *dbWrapper)

    QueryContext(ctx context.Context, q string, args ...interface{}) (*sql.Rows, error) { var ( rows *sql.Rows err error ) w.segment(ctx, q, args, func() { rows, err = w.original.QueryContext(ctx, q, args...) }) return rows, err } https://godoc.org/github.com/izumin5210/newrelic-contrib-go/nrsql