Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Coding in the context era

2 641 vues

Publié le

Introduction to why you should use change how you code now that context.Context is starting to come up in stdlib

Publié dans : Technologie
  • Soyez le premier à commenter

Coding in the context era

  1. 1. Coding in the Context Era Go Conference 2017 Spring Mar 25, 2017 Daisuke Maki @lestrrat
  2. 2. • @lestrrat • Perl/Go hacker, author, father • Author of github.com/peco/peco • Organizer for builderscon
  3. 3. uilderscon https://builderscon.io/tokyo/2017 Aug 3, 4, 5 2017
  4. 4. (we run on Kubernetes)
  5. 5. </advertisement>
  6. 6. Web+DB Press vol 98 (Apr 2017)
  7. 7. you DO use context.Context, right?
  8. 8. obj.Start() obj.Stop()
  9. 9. func (t *Obj) Start() { go func() { for { select {
 case <-t.done: … default: } … }() } } }
  10. 10. func (t *Obj) Stop() { close(t.done) }
  11. 11. THIS IS NOT SAFE
  12. 12. obj.Start() obj.Start() // What?!
  13. 13. API is ambiguous • Does it start a new goroutine every time Start() is called? • Does it error from the second one?
  14. 14. Only start one? • Maybe Start() can return an error if it has already been started • Bonus points: can it be re-entrant? • Requires state synchronization
  15. 15. func (obj *Obj) Start() error { obj.mu.Lock() if obj.started { obj.mu.Unlock() return errors.New(`already running`) } obj.started = true obj.mu.Unlock() … }
  16. 16. func (obj *Obj) Start() error { … go func() { defer func() { obj.mu.Lock() obj.started = false obj.mu.Unlock() }() for { … } }() }
  17. 17. func (obj *Obj) Start() error { … go func() { for { select { case <-obj.done: return default:
 } } … }() }
  18. 18. func (obj *Obj) Stop() error { obj.mu.Lock() if obj.started { close(obj.done) obj.mu.Unlock() return errors.New(`already running`) } obj.started = true obj.Unlock() }
  19. 19. This is still a simplified version.
  20. 20. Life is too short for manual synchronization of concurrently executed code 人類に並行実行されている コードの手動同期は難しすぎる…!
  21. 21. Nobody wants to do this
  22. 22. Root cause: shared resource • obj.started is shared • There is no way to escape manual locking
  23. 23. TRUTH YOU WILL MAKE A MISTAKE WHEN MANUALLY SYNCHRONIZING sync.Mutexes
  24. 24. AVOID sync.Mutex (unless you know what you are doing)
  25. 25. context.Contextcontext.Context
  26. 26. context.Context • abstracts away shared state for cancellation
  27. 27. context.Context • Explicit cancellation • Timeouts • Deadlines • It’s a pattern: you can use it anywhere!
  28. 28. // To save some typing, please assume the // following for the rest of this talk: ctxbg := context.Background() delay := 5 * time.Second
  29. 29. func (obj *Obj) Run(ctx context.Context) error { for { select { case <-ctx.Done(): return nil default: } … } }
  30. 30. ctx, cancel := context.WithCancel(ctxbg) go obj.Run(ctx) // later in your code cancel()
  31. 31. No sync.Mutex!
  32. 32. Clean, explicit grouting termination
  33. 33. No ambiguous API
  34. 34. ctx, cancel := context.WithTimeout(ctxbg, delay) defer cancel() go obj1.Run(ctx) // use a diff. ctx if need be go obj2.Run(ctx) // re-entrant! yay! go obj3.Run(ctx) Explicit semantics
  35. 35. YESSS!!!!
  36. 36. Prediction/Recommendation • Almost everything that can (1) block or (2) spawn a goroutine will support context.Context very soon. • You should use context.Context for anything that blocks!
  37. 37. Learn to ♡ contexts
  38. 38. Questions?

×