Skip to content

Instantly share code, notes, and snippets.

@zeisss
Created June 11, 2015 20:59
Show Gist options
  • Save zeisss/98f5bb5d6c01fe62225e to your computer and use it in GitHub Desktop.
Save zeisss/98f5bb5d6c01fe62225e to your computer and use it in GitHub Desktop.
Second Golang Meetup - Go Channels 101
# Go Channels
Dennis - dennis@giantswarm.io or @denderello
Stephan - stephan@giantswarm.io 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