Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

Coding in the context era

Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Prochain SlideShare
go 1.8 net/http timeouts
go 1.8 net/http timeouts
Chargement dans…3
×

Consultez-les par la suite

1 sur 38 Publicité

Plus De Contenu Connexe

Diaporamas pour vous (20)

Publicité

Similaire à Coding in the context era (20)

Plus par lestrrat (20)

Publicité

Plus récents (20)

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?

×