This is a creation in Article, where the information may have evolved or changed.
Golang's Channel
Channel is a very important concept for Golang, if you are a developer who is just beginning to use Golang, you may not have really touched on this concept, this article we will analyze the Golang channel
1. Introduction
To speak the Channel can not open the Goroutine--the association. Gossip does not say directly to the last example
Goroutine Demo:
package mainimport ( "fmt" "time")func main() { 1 go doSomeCompute(origin) time.Sleep(5 * time.Second)}funcint) { 2 fmt.Println(result) return}
In a nutshell, the example has a co-process of Main, a dosomecompute. There is also a delay-out method waiting to calculate the result of the calculation process. We try to think about some of the problems of this example:
A. How do I get the calculation results of Dosomecompute?
B. How do I get the execution status of Dosomecompute, which is currently running or executing?
How to solve this problem?
channel!
2. Channel
How does the channel deal with the above problem? We directly on the code:
Example
package mainimport ( "fmt")func main() { 1 //一个无缓冲Channel make(chanint) go doSomeCompute(origin, res) fmt.Println(<-res)}funcintchanint) { 2 res <- result}
In the example, the Channel acts as a bridge between the communication of the co-process. The Channel can be passed to the coprocessor to show that it is thread-safe, as is the case with the fact. The channel can be understood as a pipeline, the Dosomecompute writes the result to the channel, and the result is read in main. Note that the area where the Channel is read in the example is blocked until the result is obtained, which solves the problem A and B.
2. Directionality of Channel
In the example above, the computational process is responsible for calculating and writing the results to the channel, and if we want to ensure that the computational process does not read data from the channel, what should I do? Very simple, see example:
funcintchanint) { 2 res <- result}
The declaration of this parameter chan<- int
indicates that the function can only speak data to the Channel, and cannot read the data from it. The format of the data in the Channel is later int
represented. Similarly, a Channel that can only read data can be declared as <-chan int
. In the example, a Channel without a direction declaration can be written or read.
3. Blocking properties
The read and write operations of the Channel are blocked inside the respective threads. For example fmt.Println(<-res)
, this statement blocks until the calculation process is put into the calculation and can be read out. In other words, the association blocks until the res
data is read from.
Note that the non-buffered channel reads and writes are blocked, and a buffered channel can keep writing data to it until the cache is full before it blocks. Read the data in the same vein until the Channel is empty.
Use a typical example to illustrate the difference between buffered and non-buffered Channel:
package mainimport"fmt"funcchanint) { fmt.Println("deadlock test") <- ch}func main() { make(chanint) 1 go doSomeCompute(ch)}
Example, the main process will write to the ch
data, which is blocked, that is, the doSomeCompute
Association can not execute the program deadlock. The output is as follows:
fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan send]:main.main() C:/mygo/src/demo/blog.go:12 +0x73exit status 2
If you change to a buffered Channel:
package mainimport ( "fmt" "time")funcchanint) { fmt.Println("deadlock test") <- ch}func main() { make(chanint1) 1 go doSomeCompute(ch) time.Sleep(1 * time.Second)}
There is no blocking after writing with a buffered Channel (the next write will be blocked) and the program will continue to execute.
4. Data structure of Channel
The Channel is actually a data structure in Golang. In the Golang source code, the Channel data structure Hchan is defined as follows:
struct Hchan{ uint32 qcount; // total data in the q uint32 dataqsiz; // size of the circular q uint16 elemsize; bool closed; uint8 elemalign; Alg* elemalg; // interface for element type uint32 sendx; // send index uint32 recvx; // receive index WaitQ recvq; // list of recv waiters WaitQ sendq; // list of send waiters Lock;};
Time Rush, this time on the Channel introduction write a bit simple rough, next time write.