-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchannels.slide
97 lines (53 loc) · 3.37 KB
/
channels.slide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
Channels
Go concurrency bootcamp #1
28 May 2013
Tags: concurrency, bootcamp
Author: Joel Eidsath
http://gammafn.com/cv
* Why is Go great?
We can run more than one function at once!
.play channels/simple.go /START OMIT/,/END OMIT/
* Channels
The "go func" invocations in the last example -- _goroutines_ -- need to be able to talk to each other. In Go, we do this with _channels_.
* Synchronization with channels
The two "sayit" functions each wait for a send to the cc channel. One function accepts that send and executes. Similarly, the sends from main() wait for a receiver before proceeding. Synchronization achieved!
.play channels/simple2.go /START OMIT/,/END OMIT/
* Buffered and unbuffered channels
I used to be very confused by the two types of channels!
.code channels/channel_types.go /START OMIT/,/END OMIT/
Ugh. Are these supposed to be like C arrays?
Why does everything have to be so complicated?!?
* Blocking
Channel buffering is simple once we understand blocking.
A goroutine runs until it _blocks_. For now, let's say this means that a goroutine runs until it has to read from or write to a channel.
If the channel is not ready to accept or output data, the goroutine blocks.
The point of a channel is not _what_ it stores, but _when_ it blocks.
* Blocking example
.play channels/blocking.go /START OMIT/,/END OMIT/
* Unbuffered channels
The last example was an unbuffered channel. The two things to remember are:
- Receives to an unbuffered channel block until there is a goroutine waiting to send.
- Sends to an unbuffered channel block until there is a goroutine waiting to receive.
* Buffered channels
Buffered channels have two more rules. We can receive from a buffered channel if:
- There is a blocked goroutine waiting to send
- There is data in the buffer
We can send to a channel if:
- There is a blocked goroutine waiting to receive
- The buffer is not full
The properties of buffered channels are useful when we want to limit the number of things going on at once.
* Resource exhaustion
Without a limit on resource usage, we get panic in this code because too much memory is used!
.play channels/buffered_crash.go /START OMIT/,/END OMIT/
* Solution through a buffered channel
Now we only run three heavy processing routines at once. See the Resources bootcamp (#2) for more on this technique.
.play channels/buffered_works.go /START OMIT/,/END OMIT/
* Closed channels
These is actually one last rule for receiving from a channel. We can always receive from a buffered or unbuffered channel if it is closed. The receive returns a zero value for the channel type and the error value is set to false.
.play channels/closed.go /START OMIT/,/END OMIT/
The error value can be checked manually, but what this really allows us to do is to use the `range` keyword to iterate through a channel.
* Sending and Receiving. A discussion about terminology
The Go documentation and community discussion groups often talk about "sends on" a channel and "receives on" a channel.
Do they mean sends to a channel? Or a channel sending to something else? Is the channel receiving data? Or is data being received from the channel?
In the Go documentation, _a_channel_is_always_the_object_of_the_verbs_send_and_receive_. Therefore, we send to a channel, or we receive from a channel. A channel never "sends to" anything else. Hopefully this terminology will be cleaned up eventually!