Don’t communicate by sharing memory, communicate by sharing memory.

Go supports the concurrency model in two ways: 3, Communicating sequential processes(CSP), which is the basis for implementing goroutine and Channel concurrency models, and shared memory multithreading, which is the traditional way of sharing memory, The multithreaded model.

How to understand CSP? In simple terms, the state of different Goroutines is maintained concurrently by passing values between different Goroutines, but the use and modification of variables is limited to a single Goroutine.

define

The units of activity that can be executed concurrently in Go are called Goroutines. When a Go program starts, a goroutine that performs the main function is created, called the Main Goroutine. A new Goroutine can be created using a go statement like this: go f(), where f is a function. When a new Goroutine is opened with the GO statement, function calls following the GO statement are executed in the new Goroutine without blocking the current program execution.

If a Goroutine is a Go program that executes concurrently, a channel is the connection channel between them, providing a mechanism for goroutines to communicate with each other. A channel is typed. The type used in a channel is called element Type. For example, a channel of type int is written as chan int.

Go creates a channel using the make built-in function.

ch := make(chan int)
Copy the code

As with map, a channel refers to the underlying data structure created by make. When passing a channel as a function parameter, it actually copies a reference, which means that the function references the same data structure inside and outside the function. So you can change the value of channel directly inside the function. Like any other reference type, a channel’s zero value is nil.

A channel is comparable

Channels are comparable. If two channels are of the same type, they can be compared to each other:

ch01 := make(chan int)
ch02 := make(chan int)
if ch01 == ch02 {
    fmt.Println("ch01 == ch02")}else {
    fmt.Println("ch01 ! = ch02") // return
}
Copy the code

Two channel comparisons that are not nil actually compare whether their references are the same, if they both reference the same channel, they are the same:

func main(a) {
    ch01 := make(chan int)
    func02(ch01, ch01)
}

func func02(a chan int, b chan int) {
    if a == b {
        fmt.Println("a == b") // return}}Copy the code

Of course a channel can also be compared to nil, and an uninitialized channel is nil:

var ch02 chan int
if ch02 == nil {
    fmt.Println("ch02 is nil") // return
}
Copy the code

Basic operation of a channel

A channel has three basic operations send, receive, and close.

send

A channel supports send, which means sending data to a channel. Go uses the <- operator to implement send:

ch <- x //send
Copy the code

The sent object is <- to the right of the channel.

receive

Channels also support receive, which means to fetch data from a channel, and Go uses the <- operator to receive:

x, ok := <- ch //receive
Copy the code

Receive <- On the left, if a receive is performed without any variable assigned, the value is discarded. Receive takes two arguments, ok is used to determine whether a channel is closed or not. Fetching a value from a closed channel returns zero, in an endless loop

The receive operation is often used for state synchronization:

<- ch
Copy the code

close

A channel also supports a third operation, close. If a channel is closed, it does not send any more values. If it continues to receive, when the value of the channel is exhausted, The zero value of the corresponding element type is returned. If you send a channel, panic will occur:

close(ch)
ch <- x  // panic
Copy the code

The close operation is often used with the for statement to indicate that a channel does not generate new values:

for x := range ch {
   fmt.Print(x) 
}
Copy the code

After closing the channel, the for loop ends.

The original