Created
June 11, 2015 20:59
-
-
Save zeisss/98f5bb5d6c01fe62225e to your computer and use it in GitHub Desktop.
Second Golang Meetup - Go Channels 101
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Go Channels | |
Dennis - [email protected] or @denderello | |
Stephan - [email protected] or @zeisss_public | |
> "Don't communicate by sharing memory, share memory by communicating." -- Rob Pike | |
## Problem | |
Unsynchronized access can corrupt internal states of variables, | |
e.g. maps, slices etc. | |
Solution: | |
* Synchronise access via Mutex or | |
* Use channels | |
## Channels | |
Used for communication between Goroutines. | |
``` | |
# Create a channel (can be any type) | |
c := make(chan int) | |
# Write a value (blocking!) | |
c <- 1 | |
# Read it (other goroutine!) | |
i := <- c | |
``` | |
## Example: Simple Sequence 1/2 | |
``` | |
func Seq(max int) chan int { | |
c := make(chan int) | |
go func() { | |
for i := 0;i < max; i++ { | |
c <- i | |
} | |
}() | |
return c | |
} | |
``` | |
## Example: Simple Sequence 2/2 | |
``` | |
func main() { | |
c := Seq(10) | |
for { | |
fmt.Println(<-c) | |
} | |
} | |
``` | |
### Output | |
http://play.golang.org/p/8Orwt59nOR | |
``` | |
[...] | |
8 | |
9 | |
fatal error: all goroutines are asleep - deadlock! | |
goroutine 1 [chan receive]: | |
main.main() | |
/tmp/sandbox195620736/main.go:18 +0x80 | |
``` | |
## Channels blocking! | |
* Reading and writing channels is a blocking operation! | |
* To prevent readers for blocking forever, close channels | |
close(c) | |
Best practive: Close in writer! Writing a closed channel panics. | |
* Closed channels return the empty value (http://play.golang.org/p/Ki3cG9FoZ4) | |
c := make(chan int) | |
close(c) | |
i := <- c // i == 0 | |
* Use special receive to detect closed channels | |
i, ok := <- c // i == 0, ok == false | |
## Better Version | |
``` | |
close(c) | |
[...] | |
func main() { | |
c := Seq(10) | |
for { | |
i, ok := <- c | |
if !ok { | |
return | |
} | |
fmt.Println(i) | |
} | |
``` | |
http://play.golang.org/p/yd2BwL28SJ | |
## Even easier: Use for-loops and range to consume channels #mindblown | |
``` | |
c := Seq(10) | |
for i := range c { | |
fmt.Println(i) | |
} | |
``` | |
For-range loops until channel is closed. | |
http://play.golang.org/p/KmuvVuVVWJ | |
## More: Read/Write-Only types | |
``` | |
var myReadOnlyChannel <-chan int | |
var myWriteOnlyChannel chan<- int | |
``` | |
## More: Buffered Channel | |
``` | |
# Can hold up to 2 values | |
func main() { | |
c := make(chan int, 2) | |
c <- 1 // Does not block! | |
c <- 2 | |
fmt.Println(<- c) // = 1 | |
fmt.Println(<- c) // = 2 | |
<- c // channel empty, blocks => deadlock! | |
} | |
``` | |
http://play.golang.org/p/SrI2j0-QxY | |
## More: Multi-Channel operations (select) | |
``` | |
for { | |
select { | |
case job := <-jobQueue: | |
job() | |
case <-cancelChannel: | |
fmt.Println("Ok, I am done here. Quitting..") | |
return | |
} | |
} | |
``` | |
http://play.golang.org/p/oTUbJymNE9 | |
## Timeouts | |
``` | |
select { | |
case job := <-jobQueue: | |
job() | |
case <- time.After(30 * time.Second): | |
fmt.Println("Ok, I am done here. Timeout reached. Quitting..") | |
doneChannel <- struct{}{} | |
} | |
``` | |
http://play.golang.org/p/uQsrgY2fo_ | |
## Writes + Reads together | |
``` | |
select { | |
case <-cancel: | |
return | |
case result <- i: | |
i += 1 | |
if i > max { | |
return | |
} | |
} | |
``` | |
http://play.golang.org/p/BQ6CKtQW_2 | |
## Code-Review | |
parallel() - Execute the following batch of tasks, but only `n` tasks in parallel. Returns a channel for errors and a cancel-channel | |
https://gist.github.com/ZeissS/a2bad0bdb9f2f921933d | |
## Off-Topic: sync.Mutex | |
``` | |
lock := sync.Mutex{} | |
... | |
lock.Lock() | |
defer lock.Unlock() | |
``` | |
## links | |
* Rob Pike - https://talks.golang.org/2012/concurrency.slide#26 | |
* Effective Go - https://golang.org/doc/effective_go.html#concurrency |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment