true, "author"=>"björn", "date"=>2020-02-16 23:00:00 +0800, "layout"=>"presentation", "slug"=>"go-channels", "title"=>"Go channels", "subtitle"=>"…a means of communication", "description"=>"Takeaways from learning to use channels in Go.", "categories"=>["programming", "go"], "content"=>"\n
Go Channels
\n
…a means of communication
\n\n \n\n
Björn Andersson
\n\n\n\n
Quick thing about Go
\n\n
\n
\n Does not have threads\n
\n
Instead has \"go routines\"
\n
Kind of like a \"green/lightweight\" thread
\n
Many go routines in one thread and many threads to a program
\n
\n
\n
\n You have to write your code as if it could go into another thread at any point\n
\n
\n\n\n\n \n
What?
\n\n
\n
\n Channels are for letting different parts of the code communicate\n
\n
In Go, you never know if you're in a thread or not
\n
The fastest way of sharing sharing state is over a\n channel\n
\n
\n \n\n \n
No globals?
\n
\n
Of course, we still have globals and mutexes
\n
But prefer to send a message on a channel!
\n
\n \n\n\n\n \n
Syntax and usage
\n\n
\n
stopChan := make(chan bool), create a channel
\n
<-c: read from a channel
\n
c <-: write to a channel
\n
\n \n\n \n
Passing channels
\n
\n
\n Used when specifying which channel you want in your functions and interfaces\n
\n
name <-chan string: read-only
\n
name chan<- string: write-only
\n
\n \n\n\n\n
Types of channels
\n\n
\n
Unbuffered
\n
Buffered
\n
Closed
\n
\n\n\n\n \n
Unbuffered
\n\n
\n
Holds a single value at a time
\n
You only continue as soon as someone reads from the\n channel\n
Before it has n values in it doesn't wait for someone to\n read\n
\n
Is practically the same as a buffered with 1 as n
\n
\n \n\n \n
Buffered concurrent execution
\n
With channels you can share a limited resource across unlimited concurrency
\n\n \n
\nvar dbConns []*DB.Conn // assume it contains 5 connections\ndbPool := make(chan *DB.Conn, 5)\nfor i := 0; i < 5; i++ {\n dbPool <-dbConns[i]\n}\n\nt.Run(\"parallel test run 1\", func (t *testing.T) {\n t.Parallel()\n db := <- dbPool\n defer func () { dbPool <- db }() // returns to pool\n // run lots of tests\n})\n
\n\n \n\n\n\n \n
Closed
\n\n
\n
Will return the default value immediately
\n
You can always ask a channel if its open when reading by asking for\n a second boolean parameter\n
\n
\n \n\n \n
Closed example
\n\n
\nstopChan := make(chan struct{})\n\nclose(stopChan) // No value written to the channel\nv, ok := <- stopChan\nfmt.Printf(\"v=%v, open=%v\\n\", v, ok) // v=false, open=false\nv, ok = <- stopChan\nfmt.Printf(\"v=%v, open=%v\\n\", v, ok) // v=false, open=false\n
\n \n\n\n\n \n
Tips
\n\n
\n
\n Think about about your lines of communication\n
\n
Only one Go routine writes and one reads — don't do both in the\n same\n
\n
Who is leading the communication?
\n
Who is charge of telling the routine to shut down?
\n
\n
\n
Does a started Go routine have a reason to communicate something\n back?\n
Before it has n values in it doesn't wait for someone to
read
Is practically the same as a buffered with 1 as n
Buffered concurrent execution
With channels you can share a limited resource across unlimited concurrency
var dbConns []*DB.Conn // assume it contains 5 connections
dbPool := make(chan *DB.Conn, 5)
for i := 0; i < 5; i++ {
dbPool <-dbConns[i]
}
t.Run("parallel test run 1", func (t *testing.T) {
t.Parallel()
db := <- dbPool
defer func () { dbPool <- db }() // returns to pool
// run lots of tests
})
Closed
Will return the default value immediately
You can always ask a channel if its open when reading by asking for
a second boolean parameter
Closed example
stopChan := make(chan struct{})
close(stopChan) // No value written to the channel
v, ok := <- stopChan
fmt.Printf("v=%v, open=%v\n", v, ok) // v=false, open=false
v, ok = <- stopChan
fmt.Printf("v=%v, open=%v\n", v, ok) // v=false, open=false
Tips
Think about about your lines of communication
Only one Go routine writes and one reads — don't do both in the
same
Who is leading the communication?
Who is charge of telling the routine to shut down?
Does a started Go routine have a reason to communicate something
back?