Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

The async/await concurrency pattern in Golang

46 views

Published on

In this talk, I spoke about parallelism and concurrency and how you can achieve the same behavioral pattern you can achieve with Node.js using await/async statements, using goroutines and channels with Golang.

Published in: Software
  • Be the first to comment

  • Be the first to like this

The async/await concurrency pattern in Golang

  1. 1. The await/async concurrency pattern January, 29th - Torino, Toolbox Coworking …in Golang
  2. 2. Matteo Madeddu Github: @made2591 Role: Devops, AWS, miscellanea matteo.madeddu@gmail.com Work: enerbrain.com Blog: madeddu.xyz
  3. 3. A bit of history
  4. 4. Version 1.0 released March, 2012 Go first appeared in Google, 2007 November, 2009 Google announce Golang to the worldwide community June, 2017 I released a go-perceptron on Github Golang Developer Group begins in Turin January, 2020 2020 The community grows!
  5. 5. github.com/docker/engine
  6. 6. github.com/docker/engine github.com/kubernetes/kubernetes
  7. 7. github.com/docker/engine github.com/kubernetes/kubernetes github.com/hashicorp/terraform
  8. 8. github.com/docker/engine github.com/kubernetes/kubernetes github.com/hashicorp/terraform github.com/prometheus/prometheus
  9. 9. github.com/docker/engine github.com/kubernetes/kubernetes github.com/hashicorp/terraform github.com/grafana/grafana github.com/prometheus/prometheus
  10. 10. github.com/docker/engine github.com/kubernetes/kubernetes github.com/hashicorp/terraform github.com/gohugoio/hugo github.com/grafana/grafana github.com/prometheus/prometheus
  11. 11. it’s statically typed
  12. 12. it’s statically typed it’s compiled
  13. 13. it’s statically typed it’s compiled and provide interesting concurrency primitives to final users
  14. 14. Hello World package main import "fmt" func main() { fmt.Println("hello world") }
  15. 15. package main import "fmt" func main() { var a = "initial" fmt.Println(a) # initial var b, c int = 1, 2 fmt.Println(a, b) # 1, 2 var d = true fmt.Println(d) # true var e int fmt.Println(e) # 0 f := "apple" fmt.Println(f) # apple }
  16. 16. Concurrency Dealing with many things at once.
  17. 17. Concurrency Dealing with many things at once. Parallelism Doing many things at once.
  18. 18. Concurrency is the composition of independently executing processes, while parallelism is the simultaneous execution of (possibly related) computations.
  19. 19. Introducing goroutines package main import ( "fmt" "time" ) func f(from string) { for i := 0; i < 3; i++ { fmt.Println(from, ":", i) } } func main() { f("direct") go f("goroutine") go func(msg string) { fmt.Println(msg) }("going") time.Sleep(time.Second) fmt.Println("done") }
  20. 20. Introducing goroutines package main import ( "fmt" "time" ) func f(from string) { for i := 0; i < 3; i++ { fmt.Println(from, ":", i) } } func main() { f("direct") go f("goroutine") go func(msg string) { fmt.Println(msg) }("going") time.Sleep(time.Second) fmt.Println("done") } # standard function call
  21. 21. Introducing goroutines package main import ( "fmt" "time" ) func f(from string) { for i := 0; i < 3; i++ { fmt.Println(from, ":", i) } } func main() { f("direct") go f("goroutine") go func(msg string) { fmt.Println(msg) }("going") time.Sleep(time.Second) fmt.Println("done") } # standard function call # to invoke this function in a goroutine, use go f(s). This new goroutine will execute concurrently with the calling one.
  22. 22. When we run this program, we see the output of the blocking call first, then the interleaved output of the two goroutines. This interleaving reflects the goroutines being run concurrently by the Go runtime.
  23. 23. Introducing channels
  24. 24. Channels are the pipes that connect concurrent goroutines.
  25. 25. package main import "fmt" func main() { messages := make(chan string) go func() { messages <- "ping" }() msg := <-messages fmt.Println(msg) } Introducing channels
  26. 26. package main import "fmt" func main() { messages := make(chan string) go func() { messages <- "ping" }() msg := <-messages fmt.Println(msg) } # channels are typed by the values they convey Introducing channels
  27. 27. package main import "fmt" func main() { messages := make(chan string) go func() { messages <- "ping" }() msg := <-messages fmt.Println(msg) } # channels are typed by the values they convey # when we run the program the "ping" message is successfully passed from one goroutine to another via our channel. Introducing channels
  28. 28. By default sends and receives block until both the sender and receiver are ready. This property allowed us to wait at the end of our program for the "ping" message without having to use any other synchronization.
  29. 29. Philosophically, the idea behind Go is: Don't communicate by sharing memory; share memory by communicating.
  30. 30. The await/async concurrency pattern
  31. 31. The await/async is special syntax to work with Promises in a more comfortable way
  32. 32. Promise A promise is a special JavaScript object that let links production and consuming code
  33. 33. async Before a function means “this function always returns a Promise” Promise A promise is a special JavaScript object that let links production and consuming code
  34. 34. async Before a function means “this function always returns a Promise” await Works only inside async function and makes JavaScript wait until that Promise settles and returns its result Promise A promise is a special JavaScript object that let links production and consuming code
  35. 35. const sleep = require('util').promisify(setTimeout) async function myAsyncFunction() { await sleep(2000) return 2 }; (async function() { const result = await myAsyncFunction(); // outputs `2` after two seconds console.log(result); })();
  36. 36. // ... package main and imports func myAsyncFunction() <-chan int32 { r := make(chan int32) go func() { defer close(r) // work to be completed time.Sleep(time.Second * 2) r <- 2 }() return r } func main() { r := <-myAsyncFunction() // outputs `2` after two seconds fmt.Println(r) }
  37. 37. Promise.all()
  38. 38. const myAsyncFunction = (s) => { return new Promise((resolve) => { setTimeout(() => resolve(s), 2000); }) }; (async function() { const result = await Promise.all([ myAsyncFunction(2), myAsyncFunction(3) ]); // outputs `2, 3` after two seconds console.log(result); })();
  39. 39. // ... package main and imports func myAsyncFunction() <-chan int32 { r := make(chan int32) go func() { defer close(r) // work to be completed time.Sleep(time.Second * 2) r <- 2 }() return r } func main() { firstChannel, secondChannel := myAsyncFunction(2), myAsyncFunction(3) first, second := <-firstChannel, <-secondChannel // outputs `2, 3` after two seconds fmt.Println(first, second) }
  40. 40. The cool thing about channels is that you can use Go's select statement to implement concurrency patterns and wait on multiple channel operations.
  41. 41. Promise.race()
  42. 42. const myAsyncFunction = (s) => { return new Promise((resolve) => { setTimeout(() => resolve(s), 2000); }) }; (async function() { const result = await Promise.race([ myAsyncFunction(2), myAsyncFunction(3) ]); // outputs `2` or `3` after two seconds console.log(result); })();
  43. 43. // ... package main and imports func myAsyncFunction() <-chan int32 { r := make(chan int32) go func() { defer close(r) // work to be completed time.Sleep(time.Second * 2) r <- 2 }() return r } func main() { var r int32 select { case r = <-myAsyncFunction(2) case r = <-myAsyncFunction(3) } // outputs `2` or `3` after two seconds fmt.Println(r) }
  44. 44. https://tour.golang.org/ https://madeddu.xyz/posts/go-async-await/ https://blog.golang.org/concurrency-is-not-parallelism https://gobyexample.com/non-blocking-channel-operations
  45. 45. Thank you!
  46. 46. Matteo Madeddu Github: @made2591 Role: Devops, AWS, miscellanea matteo.madeddu@gmail.com Work: enerbrain.com Blog: madeddu.xyz

×