|
| 1 | +# channel Usage scenarios |
| 2 | + |
| 3 | + |
| 4 | +Channel usage scenarios (data flow) |
| 5 | + |
| 6 | +* Message passing, message filtering |
| 7 | +* Signal broadcasting |
| 8 | +* Event subscription and broadcasting |
| 9 | +* Request and response forwarding |
| 10 | +* Task distribution |
| 11 | +* Summary of results |
| 12 | +* Concurrency control |
| 13 | +* Synchronous and asynchronous |
| 14 | +``` |
| 15 | +
|
| 16 | +Basic operation and precautions of channel |
| 17 | +There are 3 states of channel: |
| 18 | +
|
| 19 | +* nil, uninitialized state, only declared, or manually assigned to nil |
| 20 | +* active, normal channel, readable or writable |
| 21 | +* closed, closed, ** Do not mistakenly believe that after closing the channel, the value of the channel is nil ** |
| 22 | +* The channel can perform 3 operations: Read, Write, Close |
| 23 | +
|
| 24 | +| Operation | nil channel | normal channel | closed channel |
| 25 | +|: --------: |: -------: |: ------: |: ----------------: | |
| 26 | +| <-ch blocking | success or blocking | zero value read | |
| 27 | +| ch <-blocking | success or blocking | panic | |
| 28 | +| close (ch) panic | Success | panic | |
| 29 | +
|
| 30 | +** 3 operations X 3 channel states = 9 scenarios combined ** |
| 31 | +
|
| 32 | +
|
| 33 | +* 1. Use for range to read channel |
| 34 | +
|
| 35 | +Scenes: |
| 36 | +
|
| 37 | +When you need to continuously read data from the channel. |
| 38 | +
|
| 39 | +Use for-range to read the channel, which is safe and convenient. When the channel is closed, the for loop will automatically exit. There is no need to actively monitor whether the channel is closed. The zero value of the data type. |
| 40 | +
|
| 41 | +usage |
| 42 | +``` |
| 43 | +for x: = range ch { |
| 44 | + fmt.Println (x) |
| 45 | +} |
| 46 | +``` |
| 47 | +
|
| 48 | +* 2. Use v, ok: = <-ch + select to determine whether the channel is closed |
| 49 | +Scenes |
| 50 | +v, ok: = <-ch + select operation to determine whether the channel is closed |
| 51 | +
|
| 52 | +The results and meaning of ok: |
| 53 | +-`true`: read the channel data, not sure if it is closed, maybe the channel has saved data, but the channel is closed |
| 54 | +-`false`: The channel is closed and no data is read. |
| 55 | +
|
| 56 | +* 3. Use select to handle multiple channels |
| 57 | +Scenes |
| 58 | +When multiple channels need to be processed simultaneously, but only the channel that occurs first is processed |
| 59 | +
|
| 60 | +Select can monitor the situation of multiple channels at the same time, and only handle unblocked cases. When the channel is nil, the corresponding case is always blocked, regardless of reading or writing. Special attention: Under normal circumstances, writing to the nil channel is panic. |
| 61 | +
|
| 62 | +
|
| 63 | +* 4. Use the channel statement to control read and write permissions |
| 64 | +Scenes |
| 65 | +When the coroutine reads or writes to a channel |
| 66 | +
|
| 67 | +purpose: |
| 68 | +
|
| 69 | +Make the code more readable and easier to maintain, |
| 70 | +Prevent the read-only coroutine from writing data to the channel, but the channel is closed, causing panic. |
| 71 | +
|
| 72 | +usage |
| 73 | +If the coroutine only writes to a channel, the channel is declared as write-only. |
| 74 | +If the coroutine only has a read operation on a channel, the channe is declared read-only. |
| 75 | +
|
| 76 | +``` |
| 77 | +// Only the generator writes outCh and returns the statement |
| 78 | +// <-chan int, can prevent other coroutines from using this channel indiscriminately, causing hidden bugs |
| 79 | +func generator (int n) <-chan int { |
| 80 | + outCh: = make (chan int) |
| 81 | + go func () { |
| 82 | + for i: = 0; i <n; i ++ { |
| 83 | + outCh <-i |
| 84 | + } |
| 85 | + } () |
| 86 | + return outCh |
| 87 | +} |
| 88 | + |
| 89 | +// consumer read-only inCh data, declared as <-chan int |
| 90 | +// Can prevent it from writing data to inCh |
| 91 | +func consumer (inCh <-chan int) { |
| 92 | + for x: = range inCh { |
| 93 | + fmt.Println (x) |
| 94 | + } |
| 95 | +} |
| 96 | +``` |
| 97 | +
|
| 98 | +* 5. Use buffered channels to enhance concurrency |
| 99 | +Scenes |
| 100 | +asynchronous |
| 101 | +
|
| 102 | +There are buffer channels for multiple coroutines to process at the same time, which can improve concurrency to a certain extent. |
| 103 | +usage |
| 104 | +``` |
| 105 | +// no buffer |
| 106 | +ch1: = make (chan int) |
| 107 | +ch2: = make (chan int, 0) |
| 108 | +// buffered |
| 109 | +ch3: = make (chan int, 1) |
| 110 | +// Use 5 `do` coroutines to process input data simultaneously |
| 111 | +func test () { |
| 112 | + inCh: = generator (100) |
| 113 | + outCh: = make (chan int, 10) |
| 114 | + |
| 115 | + for i: = 0; i <5; i ++ { |
| 116 | + go do (inCh, outCh) |
| 117 | + } |
| 118 | + |
| 119 | + for r: = range outCh { |
| 120 | + fmt.Println (r) |
| 121 | + } |
| 122 | +} |
| 123 | + |
| 124 | +func do (inCh <-chan int, outCh chan <-int) { |
| 125 | + for v: = range inCh { |
| 126 | + outCh <-v * v |
| 127 | + } |
| 128 | +} |
| 129 | +``` |
| 130 | +
|
| 131 | +* 6. Add timeout to operation |
| 132 | +Scenes |
| 133 | +Operations requiring timeout control |
| 134 | +
|
| 135 | +Use select and time.After, to see which operation and timer return first, the processing is completed first, the effect of timeout control is achieved |
| 136 | +
|
| 137 | +* 7. Use time to achieve channel non-blocking read and write |
| 138 | +Scenes |
| 139 | +I don't want to waste time on channel reading and writing |
| 140 | +
|
| 141 | +It is an extension to add a timeout to the operation. The operation here is the reading or writing of the channel |
| 142 | +Note: time.After waiting can be replaced with default, it is the effect of returning immediately when the channel is blocked |
| 143 | +
|
| 144 | +* 8. Use close (ch) to close all downstream coroutines |
| 145 | +Scenes |
| 146 | +When exiting, display to notify all coroutines to exit |
| 147 | +
|
| 148 | +All coroutines that read ch will receive the close (ch) signal |
| 149 | +
|
| 150 | +* 9. Use chan struct {} as signal channel |
| 151 | +Scenes |
| 152 | +Use channels to pass signals instead of data |
| 153 | +
|
| 154 | +When there is no data to pass, pass an empty struct |
| 155 | +
|
| 156 | +* 10. Use channel to pass pointer of structure instead of structure |
| 157 | +Scenes |
| 158 | +When using channel to transfer structure data |
| 159 | +
|
| 160 | +** The channel essentially transfers a copy of the data. The smaller the copied data, the higher the transmission efficiency. The transfer structure pointer is more efficient than the transfer structure |
| 161 | +
|
| 162 | +* 11. Use channel to pass channel |
| 163 | +Scenes |
| 164 | +There are a lot of usage scenarios, usually used to get results. |
| 165 | +
|
| 166 | +The channel can be used to pass variables, the channel itself is a variable, you can pass yourself. |
| 167 | +
|
| 168 | +Reference information: https://dave.cheney.net/2014/03/19/channel-axioms |
0 commit comments