The document discusses the Go programming language and how it differs from Ruby. It provides examples of Go code demonstrating type declarations, embedded types, exported variables and functions, and variable redeclaration. It also discusses some concepts in Go like interfaces, channels, and concurrency that are different from Ruby. The document suggests that Go teaches programmers awareness about variables, types, and errors that can improve Ruby code.
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
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.
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
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
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)
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!
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!
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)!
! }!
}
Type Declaration
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
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)!
! }!
}
Exported Array
The size in Array is part of the type!
[2]float32 != [3]float32
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)!
! }!
}
Embedding!
(Not inheritance)
77. 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
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!
}
Dimensions)!
79. 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!
}
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)!
! }!
}
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)!
!
! h := make(map[string]Hotel)!
!
! for name, _ := range h {!
! ! fmt.Println(name)!
! }!
}
Which Name should
I use?
Error: Ambiguous
selector hotel.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.Name)Hall.!
Name)!
!
! h := make(map[string]Hotel)!
!
! for name, _ := range h {!
! ! fmt.Println(name)!
! }!
}
83. 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)!
! }!
}
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
85. 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?
87. Programmer Awareness
Iterating a Hash
hotels := make(map[string]Hotel)!
!
for name, _ := range hotels {!
! fmt.Println(name)!
}
88. Programmer Awareness
Iterating a Hash
hotels := make(map[string]Hotel)!
!
for name, _ := range hotels {!
! fmt.Println(name)!
}
Map of strings and Hotels
89. Programmer Awareness
Iterating a Hash
hotels := make(map[string]Hotel)!
!
for name, _ := range hotels {!
! fmt.Println(name)!
}
Easy iteration syntax!
90. Programmer Awareness
Iterating a Hash
hotels := make(map[string]Hotel)!
!
for name, _ := range hotels {!
! fmt.Println(name)!
} Blank Identifier - ignore value
91. Programmer Awareness
Iterating a Hash
hotels := make(map[string]Hotel)!
!
for name, _ := range hotels {!
! fmt.Println(name)!
}
92. Programmer Awareness
Iterating a Hash
hotels := make(map[string]Hotel)!
!
for name, _ := range hotels {!
! fmt.Println(name)!
}
Bad practice! !
I’ll randomise the
order!
110. 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
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()
}
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()!
}
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 channel that accepts an int
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()
}
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
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 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
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 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!
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 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)!
}
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 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)!
}
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()
}
121. 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!
! ! ! }!
! ! }!
}
122. 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!
! ! ! }!
! ! }!
}
123. 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!
! ! ! }!
! ! }!
}