Skip to content

Commit 188efc0

Browse files
committed
update
1 parent 2b81785 commit 188efc0

File tree

4 files changed

+485
-0
lines changed

4 files changed

+485
-0
lines changed

EN/channel/channel-1.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
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

EN/channel/channel.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# channel
2+
3+
4+
### Essentials
5+
6+
* Channle essential data structure pipeline queue, data is first-in first-out.
7+
* With ** thread safety mechanism **, when multiple go programs are accessed, no shackles are needed, which means that the channel itself is thread safe.
8+
* Channels are typed.
9+
10+
### channel traversal mode
11+
12+
* Simple operation: data: = <-ch (if read many times, need to use loop)
13+
```
14+
var chNo = make (chan int, 6)
15+
 
16+
func ChEach () {
17+
for i: = 0; i <10; i ++ {
18+
chNo <-8 * i
19+
}
20+
 
21+
}
22+
func main () {
23+
go ChEach ()
24+
for i: = 0; i <100; i ++ {
25+
fmt.Print (<-chNo, "\ t")
26+
}
27+
}
28+
29+
```
30+
Note:
31+
(1) If there are more reads than writes: fatal error: all goroutines are asleep-deadlock!,
32+
If close (chNo)), the data read more than times is 0 (default value of data).
33+
(2) The number of reads <= the number of writes, the content corresponding to the number of reads will be read (in principle, the number of reads and writes is equal), and no error will be reported.
34+
35+
36+
37+
* Assertion method ```if value, ok: = <-ch; ok == true ()` ``
38+
    -If the writer does not write data, it is not closed. <-ch; ** will block **
39+
-If the write end writes data, value saves <-ch the read data. ok is set to true
40+
-If the write end is closed. value is the default value of the data type. ok is set to false
41+
42+
* range method ```for num: = range ch ()` ``
43+
44+
```
45+
var chNo = make (chan int, 6)
46+
 
47+
func mm1 () {
48+
for i: = 0; i <10; i ++ {
49+
chNo <-8 * i
50+
}
51+
    // Close, otherwise it will not compile
52+
close (chNo)
53+
}
54+
func main () {
55+
 
56+
go mm1 ()
57+
for {
58+
for data: = range chNo {
59+
fmt.Print (data, "\ t")
60+
}
61+
break
62+
}
63+
}
64+
```
65+
66+
** Note that when using for-range, the traversed variable assignment pointer address is unchanged! You can solve the special scenarios by declaring new variables in the loop body! **
67+
68+
Notes on traversal method:
69+
Summary: Through the above verification, in order to ensure the robustness of the program, when designing the program, it is best to read and write the channel separately in the sub-go process. After writing the data, remember to close the channel, so as to avoid blocking and cause the main program to crash, and at the same time capture the subroutine error information.
70+
71+
* Channels do not need to be closed as often as files. Only when you do not have any data to send, or you want to explicitly end the range loop, etc., do you close the channel;
72+
* After closing the channel, it is impossible to send data to the channel again (after a panic error is caused, the receiver immediately returns zero);
73+
* After closing the channel, you can continue to receive data from the channel;
74+
* For nil channel, no matter sending or receiving, it will be blocked.

0 commit comments

Comments
 (0)