Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

RubyConf Portugal 2014 - Why ruby must go!

11.025 visualizaciones

Publicado el

In this talk, I take the audience through ha whirlwind tour of Golang for Rubyists. I also discuss things like "Programmer Awareness", what can Rubyists learn from Go and how they can co-exist.

Publicado en: Software, Tecnología
  • Inicia sesión para ver los comentarios

RubyConf Portugal 2014 - Why ruby must go!

  1. Why Ruby Must Go!
  2. Why must Ruby go?
  3. Why must Ruby go?
  4. Why Ruby Must Go! What can Ruby incorporate from Go? What is Programmer Awareness? As a Rubyist, what does Go teach me?
  5. @gautamrege @joshsoftware ! @rubyconfindia
  6. Programming Paradigms Imperative Declarative Procedural Functional Object Oriented Symbolic
  7. Programming Paradigms Imperative Declarative Procedural Functional Object Oriented Symbolic C++! Java! Python! Ruby Order of execution / steps One or more subroutines
  8. Programming Paradigms Imperative Declarative Procedural Order of execution / steps One or more subroutines Functional Object Oriented Symbolic Pascal! FORTRAN! C
  9. Programming Paradigms Imperative Declarative Procedural Order of execution / steps One or more subroutines Functional Object Oriented Symbolic Pascal! FORTRAN! C! Go
  10. Go Lang C on Steroids
  11. Go Lang C on Steroids
  12. Go Lang C on Steroids • No more memory leaks. (Garbage collection)
  13. Go Lang C on Steroids • No more memory leaks. (Garbage collection) • No more pointer de-referencing. (-> or . )
  14. Go Lang C on Steroids • No more memory leaks. (Garbage collection) • No more pointer de-referencing. (-> or . ) • Support for maps, slices and channels.
  15. Go Lang C on Steroids • No more memory leaks. (Garbage collection) • No more pointer de-referencing. (-> or . ) • Support for maps, slices and channels. • Support for closures.
  16. Go Lang C on Steroids • No more memory leaks. (Garbage collection) • No more pointer de-referencing. (-> or . ) • Support for maps, slices and channels. • Support for closures. • Concurrency: closures, channels & go-routines.
  17. Go is different !
  18. Go is different !
  19. Go is different ! • No exceptions, only errors.
  20. Go is different ! • No exceptions, only errors. • Return multiple values from functions
  21. Go is different ! • No exceptions, only errors. • Return multiple values from functions • Interfaces but no classes (only structs)
  22. Go is different ! • No exceptions, only errors. • Return multiple values from functions • Interfaces but no classes (only structs) • No inheritance but embedded structs
  23. Let’s get Going And learn Go along the way!
  24. Duck Typing in Ruby
  25. Duck Typing in Ruby Programming convenience.! Implicit Type Conversions.! No complex Type Inference
  26. Duck Typing in Ruby Programming convenience.! Implicit Type Conversions.! No complex Type Inference Don’t fight the Type System
  27. Duck Typing in Ruby Programming convenience.! Implicit Type Conversions.! No complex Type Inference Don’t fight the Type System Code First - Resolve Issues Later
  28. Problems with Duck Typing
  29. Problems with Duck Typing No Early Warning System! Reactive programming! Compiler Time checks!
  30. Problems with Duck Typing No Early Warning System! Reactive programming! Compiler Time checks! Type Inference
  31. Problems with Duck Typing No Early Warning System! Reactive programming! Compiler Time checks! Type Inference Code Once Correctly
  32. Types? Who cares? We’re ! Rubyists!
  33. Types? Who cares? We’re ! Rubyists!
  34. Type Checks in Ruby! def convert_hashes_to_parameters(key, value, assign_if_converted=true)! converted = convert_value_to_parameters(value)! #...! end! ! def convert_value_to_parameters(value)! if value.is_a?(Array) && !converted_arrays.member?(value)! #...! converted_arrays << converted! converted! elsif value.is_a?(Parameters) || !value.is_a?(Hash)! #...! end! end
  35. Type Checks in Ruby! def convert_hashes_to_parameters(key, value, assign_if_converted=true)! converted = convert_value_to_parameters(value)! #...! end! ! def convert_value_to_parameters(value)! if value.is_a?(Array) && !converted_arrays.member?(value)! #...! converted_arrays << converted! converted! elsif value.is_a?(Parameters) || !value.is_a?(Hash)! #...! end! end
  36. Type Checks in Ruby! def convert_hashes_to_parameters(key, value, assign_if_converted=true)! converted = convert_value_to_parameters(value)! #...! end! ! def convert_value_to_parameters(value)! if value.is_a?(Array) && !converted_arrays.member?(value)! #...! converted_arrays << converted! converted! elsif value.is_a?(Parameters) || !value.is_a?(Hash)! #...! end! end def permit!! each_pair do |key, value|! value = convert_hashes_to_parameters(key, value)! #...! end
  37. Type Checks in Ruby! def convert_hashes_to_parameters(key, value, assign_if_converted=true)! converted = convert_value_to_parameters(value)! #...! end! ! def convert_value_to_parameters(value)! if value.is_a?(Array) && !converted_arrays.member?(value)! #...! converted_arrays << converted! converted! elsif value.is_a?(Parameters) || !value.is_a?(Hash)! #...! end! end def permit!! each_pair do |key, value|! value = convert_hashes_to_parameters(key, value)! #...! end Strong Parameters!
  38. To Duck or to Type
  39. To Duck or to Type Best of Both worlds
  40. To Duck or to Type Light weight 1-level Type check
  41. To Duck or to Type Light weight 1-level Type check type point int ! func main() { var i int = 2 var j point = 2 ! i == j }
  42. To Duck or to Type Light weight 1-level Type check type point int ! func main() { var i int = 2 var j point = 2 Variable name first, then the type ! i == j }
  43. To Duck or to Type Light weight 1-level Type check type point int ! func main() { var i int = 2 var j point = 2 ! i == j }
  44. To Duck or to Type Light weight 1-level Type check type point int ! func main() { var i int = 2 var j point = 2 ! i == j } Error: invalid operation: i == j (mismatched types int and point)
  45. Ruby re-defines Object Oriented Concepts, Go re-defines programming itself! “ ”
  46. Programmer Awareness
  47. Programmer Awareness %QORKNGT
  48. Programmer Awareness %QORKNGT 4GXKGYGT
  49. Programmer Awareness %QORKNGT 4GXKGYGT (TCOGYQTM
  50. Programmer Awareness %QORKNGT 4GXKGYGT (TCOGYQTM .CPIWCIG
  51. Programmer Awareness Variable declaration and assignment
  52. Programmer Awareness Variable declaration and assignment y y
  53. Programmer Awareness Variable declaration and assignment y := 2 // y is of type int! y = "3" Implicit declaration
  54. Programmer Awareness Variable declaration and assignment y := 2 // y is of type int! y = "3" Assignment
  55. Programmer Awareness Variable declaration and assignment y := 2 // y is of type int! y = "3" COMPLIER ERROR! cannot use “3” (type string) as type int in assignment
  56. Programmer ERROR? Variable declaration and assignment y := 2 // y is of type int! y = "3" As a programmer, we probably re-assigned “y” to a String by mistake!
  57. Programmer AWARENESS Variable declaration and assignment y := 2 // y is of type int! y, _ = strconv.Atoi("3") There’s always a right way to do things!
  58. ! Eh… what?
  59. ! Eh… what? https://flic.kr/p/mnZgQw
  60. Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! d, err := f.Stat()! }
  61. Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! d, err := f.Stat()! } import packages
  62. Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! d, err := f.Stat()! } Exported function
  63. Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! d, err := f.Stat()! }
  64. Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! d, err := f.Stat()! } I’m practical. You can re-declare err in your code!* * Conditions apply
  65. Programmer Awareness Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! d, err := f.Stat()! }
  66. Programmer Awareness Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! f, err := f.Stat()! }
  67. Programmer Awareness Variable Re-declaration import "os"! Error: no new ! variables on left func main() {! side of := ! f, err := os.Open("somefile")! ! // handle error! ! ! f, err := f.Stat()! } Hmm.. I think you re-used the variable f by mistake!
  68. Programmer Awareness Variable Re-declaration import "os"! ! func main() {! ! f, err := os.Open("somefile")! ! // handle error! ! ! f, err = f.Open("other file")! } Re-assign ! explicitly.. 
  69. With Great Power Comes Great Responsibility
  70. https://flic.kr/p/kSSWb
  71. Overloading but first …
  72. Lets Go a little more! type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Dimensions)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } Type Declaration
  73. Lets Go a little more! type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Dimensions)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } Exported Array
  74. Lets Go a little more! type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Dimensions)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } Exported Array The size in Array is part of the type! [2]float32 != [3]float32
  75. Lets Go a little more! type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Dimensions)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } Embedding! (Not inheritance)
  76. Lets Go a little more! type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Dimensions)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } hotel.Dimensions and not hotel.Hall.Dimensions
  77. Lets Go a little more! func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Name)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } Dimensions)!
  78. Lets Go a little more! func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Name)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! }
  79. Programmer Awareness type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Name)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! }
  80. Programmer Awareness type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Name)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! } Which Name should I use? Error: Ambiguous selector hotel.Name!
  81. Programmer Awareness type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Name)Hall.! Name)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! }
  82. Programmer Awareness type Layout struct {! ! Name string! Capacity int! }! ! type Hall struct {! ! Name string! ! Dimensions [2]float32! }! ! type Hotel struct {! ! Location string! ! Hall! ! Layout! } func main() {! ! hotel := Hotel{}! ! fmt.Println(hotel.Hall.Name)! ! ! h := make(map[string]Hotel)! ! ! for name, _ := range h {! ! ! fmt.Println(name)! ! }! }
  83. Modules in Ruby module Layout! def manager! p "Layout Manager"! end! end! ! module Hall! def manager! p "Hall Manager"! end! end! ! class Hotel! include Layout! include Hall! end def main! hotel = Hotel.new! p hotel.manager! end
  84. Modules in Ruby module Layout! def manager! p "Layout Manager"! end! end! ! module Hall! def manager! p "Hall Manager"! end! end! ! class Hotel! include Layout! include Hall! end def main! hotel = Hotel.new! p hotel.manager! end Which language is this dude?
  85. Include modules in order! https://flic.kr/p/e7SnAa
  86. Programmer Awareness Iterating a Hash hotels := make(map[string]Hotel)! ! for name, _ := range hotels {! ! fmt.Println(name)! }
  87. Programmer Awareness Iterating a Hash hotels := make(map[string]Hotel)! ! for name, _ := range hotels {! ! fmt.Println(name)! } Map of strings and Hotels
  88. Programmer Awareness Iterating a Hash hotels := make(map[string]Hotel)! ! for name, _ := range hotels {! ! fmt.Println(name)! } Easy iteration syntax!
  89. Programmer Awareness Iterating a Hash hotels := make(map[string]Hotel)! ! for name, _ := range hotels {! ! fmt.Println(name)! } Blank Identifier - ignore value
  90. Programmer Awareness Iterating a Hash hotels := make(map[string]Hotel)! ! for name, _ := range hotels {! ! fmt.Println(name)! }
  91. Programmer Awareness Iterating a Hash hotels := make(map[string]Hotel)! ! for name, _ := range hotels {! ! fmt.Println(name)! } Bad practice! ! I’ll randomise the order!
  92. Ordered Hashes!
  93. Ordered Hashes!
  94. Pushing some Goodies into Ruby https://flic.kr/p/awu6ZA
  95. Defer mu sync.Mutex! ! func foo() {! mu.Lock()! defer mu.unLock()! // do something...! } https://flic.kr/p/awu6ZA
  96. Defer func trace(s string) { fmt.Println("entering:", s) }! func untrace(s string) { fmt.Println("leaving:", s) }! ! func a() {! trace("a")! defer untrace("a")! // do something....! } https://flic.kr/p/awu6ZA
  97. Concurrency Parallelism Multi-core Processing https://flic.kr/p/awu6ZA
  98. Example - Relay Race • 4 legs of the race • Each leg does processing concurrently. • Completion should be in order. (pass the baton)
  99. Concurrent Example Leg 1 Leg 2 Leg 3 Leg 4
  100. Concurrent Processing Leg 1 Leg 2 Leg 3 Leg 4 CPU churn - CPU time consuming operation.
  101. Completion Order Leg 1 Leg 2 Leg 3 Leg 4
  102. Completion Order Leg 1 Leg 2 Leg 3 Leg 4
  103. Completion Order Leg 1 Leg 2 Leg 3 Leg 4
  104. Completion Order Leg 1 Leg 2 Leg 3 Leg 4
  105. CSP! Communicating Sequential Processes https://flic.kr/p/6MwYFo https://flic.kr/p/awu6ZA
  106. CSP! Communicating Sequential Processes since 1978 !! https://flic.kr/p/awu6ZA https://flic.kr/p/6MwYFo
  107. package main ! import ( "fmt" "runtime" "sync" ) ! var wg sync.WaitGroup ! /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1
  108. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() }
  109. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) ! for i := 1; i < 5; i++ {! go run(i, baton)! }! ! ! ! ! // start the race! baton <- 1! ! // wait for relay to finish! wg.Wait()! }
  110. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) ! for i := 1; i < 5; i++ {! go run(i, baton)! }! ! ! ! ! // start the race! baton <- 1! ! // wait for relay to finish! wg.Wait()! } A channel that accepts an int
  111. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) ! for i := 1; i < 5; i++ {! go run(i, baton)! }! ! ! ! ! // start the race! baton <- 1! ! // wait for relay to finish! wg.Wait()! } Go Routine
  112. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) ! for i := 1; i < 5; i++ {! go run(i, baton)! }! ! ! ! ! // start the race! baton <- 1! ! // wait for relay to finish! wg.Wait()! } Writing to a channel
  113. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) ! for i := 1; i < 5; i++ {! go run(i, baton)! }! ! ! ! ! // start the race! baton <- 1! ! // wait for relay to finish! wg.Wait()! } A WaitGroup - wait for 4 events!
  114. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() }
  115. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func run(leg int, baton chan int) { defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) ! ! ! // Massive CPU churn! ! ! for count := 0; count < 300; count++ {! ! ! ! for char := 0; char < 30000; char++ {! ! ! ! fmt.Printf("")! ! ! ! }! ! ! }! fmt.Printf("Leg %d.. churned, waiting to ! ! ! check_baton(leg, baton)! }
  116. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func run(leg int, baton chan int) { defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) Done for WaitGroup ! ! ! // Massive CPU churn! ! ! for count := 0; count < 300; count++ {! ! ! ! for char := 0; char < 30000; char++ {! ! ! ! fmt.Printf("")! ! ! ! }! ! ! }! fmt.Printf("Leg %d.. churned, waiting to ! ! ! check_baton(leg, baton)! }
  117. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() }
  118. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func check_baton(leg int, baton chan int) {! ! ! for value := range baton {! ! ! ! switch value {! ! ! ! ! case leg:! ! ! ! ! ! // pass the baton! ! ! ! ! ! fmt.Println("Finished leg ", leg)! ! ! ! ! ! if leg == 4 {! ! ! ! ! ! ! close(baton)! ! ! ! ! ! } else {! ! ! ! ! ! ! ! baton <- leg + 1! ! ! ! ! ! }! ! ! ! ! ! return! ! ! ! ! default:! ! ! ! ! ! // ignore! ! ! ! ! ! baton <- value! ! ! ! }! ! ! }! }
  119. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func check_baton(leg int, baton chan int) {! ! ! for value := range baton {! ! ! ! switch value {! ! ! ! ! case leg:Read ! or block on a ! ! ! ! ! // pass the channel baton! ! ! ! ! ! fmt.Println("Finished leg ", leg)! ! ! ! ! ! if leg == 4 {! ! ! ! ! ! ! close(baton)! ! ! ! ! ! } else {! ! ! ! ! ! ! ! baton <- leg + 1! ! ! ! ! ! }! ! ! ! ! ! return! ! ! ! ! default:! ! ! ! ! ! // ignore! ! ! ! ! ! baton <- value! ! ! ! }! ! ! }! }
  120. Channels in action p!ackage main import ( "fmt" "runtime" "sync" )! v!ar wg sync.WaitGroup /* * Each go-routine sleeps at random(1-5) seconds. * This is simulating long working process * Then we finish in order */ func check_baton(leg int, baton chan int) { for value := range baton { switch value { case leg: // pass the baton fmt.Println("Finished leg ", leg) if leg == 4 { close(baton) } else { baton <- leg + 1 } return default: // ignore baton <- value } } }! func run(leg int, baton chan int) { ! defer wg.Done() fmt.Printf("Leg %d.. churningn", leg) // Massive CPU churn for count := 0; count < 300; count++ { for char := 0; char < 30000; char++ { fmt.Printf("") } ! } fmt.Printf("Leg %d.. churned, waiting to exitn", leg) ! check_baton(leg, baton) }! func main() { runtime.GOMAXPROCS(4) ! baton := make(chan int) wg.Add(4) for i := 1; i < 5; i++ { ! go run(i, baton) } ! // start the race baton <- 1 // wait for relay to finish wg.Wait() } func check_baton(leg int, baton chan int) {! ! ! for value := range baton {! ! ! ! switch value {! ! ! ! ! case leg:! ! ! ! ! ! // pass the baton! ! ! ! ! ! fmt.Println("Finished leg ", leg)! ! ! ! ! ! if leg == 4 {! ! ! ! ! ! ! close(baton)! ! ! ! ! ! } else {! ! ! ! ! ! ! ! baton <- leg + 1! ! ! ! ! ! }! ! ! ! ! ! return! ! ! ! ! default:! ! ! ! ! ! // ignore! ! ! ! ! ! baton <- value! ! ! ! }! ! ! }! }
  121. The Big Fight https://flic.kr/p/9AeqD2
  122. Generics? Convenient Too early still. interface{} https://flic.kr/p/9AeqD2
  123. Keywords! Nah.. no rules, https://flic.kr/p/9AeqD2 rules! You need’em bro
  124. GIL https://flic.kr/p/9AeqD2  Compiled language FTW
  125. Extending & Embedding https://flic.kr/p/9AeqD2 Yeah Nope. ! Only Cgo
  126. Tooling https://flic.kr/p/9AeqD2 gem bundler go tools
  127. Emergency Instructions ! OR ! Lecture In Aerodynamics
  128. Emergency Instructions
  129. Emergency Instructions
  130. Traction Control! Fuel Efficiency! Aerodynamics! Tyre Temperature
  131. Traction Control! Fuel Efficiency! Aerodynamics! Tyre Temperature
  132. “ Ruby is for developers Go is for programmers ” @gautamrege @joshsoftware

×