Go keyword --chan

chan

Chan is also called a channel. The form is similar to a pipe. The content is sent from one end and read from the other. Here's how to define a channel:

Var variable namechan dataType

When defining a channel, you need to specify the data type, that is, only variables of this specified data type are allowed to pass through this channel.

Initialization channel

When you initialize a channel type variable in golang, you can divide the channel into two cases, one is a buffered channel and the other is a channel without buffering. Here are the initialization methods for the next two cases:

// Initialize the channel without buffering, the data type in the channel is int
var ch1 = make(chan int)

/ / Initialize the channel with 10 buffers, the data type in the channel is string
var ch2 = make(chan string,10)

Another way to write is to define and initialize the channel.

// Define the channel and initialize 8 buffers for the channelch3 :=make(chan int ,8)

// Define the channel and initialize it to no buffered channelch4 :=make(chan string)

Channel assignment

Both the reading and writing of the channel may enter a blocking state.

  1. Without a buffered channel, blocking occurs when writing, and the blocking is not completed until the information in the channel is read.
  2. With buffered channels, each time a message is written to the channel, the channel length is incremented by one. Each time the information is successfully read from the channel, the channel length is decremented by one. If the channel length is equal to the channel buffer length, continuing to write information to the channel will block the program; if the channel length is less than the channel buffer length, writing information to the channel will not cause blocking. If the channel length is 5, then if the channel is not read, the program will be blocked when the information is written to the sixth time in the channel.

The syntax for channel writing is:

var ch = make(chan string,10)

// Write the string "hello" to the channel, adding 1ch <-"hello"

Read channel

Channel is empty   1. The channel is not closed, the program will enter the blocking state, and the channel will be written.   2. The channel is closed, does not block, and returns the initial value of the data type in the channel (dirty data). If the channel is chan int, the return value is 0. When the channel is chan string, the return value is null.   Channel is not empty   1. The channel is not closed, the information is read once from the channel, and after the reading is completed, the execution is performed.   2. The channel has been closed, read a message from the channel, and after the reading is completed, execute it down.

Read channel operation:

val,ok := <-ch

Use the assertion to read the value in the channel, check if the channel has content, and determine if the channel is closed. When there is no information in the channel and the channel is closed, the ok value is false. When the channel is not closed, there is no information in the channel. The program will block. If there is content in the channel, the ok value is true.

Another way to read channels without using assertions

val := <-ch

Write and read channels

Example of reading a channel without buffer:

package main

import (
    "fmt"
)

func main() {
    / / Define a channel without buffer, the data type in the channel is int
    var c = make(chan int)

    // Open a Ctrip and read the contents of the channel
    go func() {
        fmt.Println("Write information is:", <-c)
    }()// Write data to the channelc <- 1
}

Output result:

Write information is: 1

When reading or writing a buffered channel, as long as the data length in the channel is not greater than the buffer length, there will be no blocking, but when the buffered channel is read and there is no content in the channel, the program will still enter the blocking state. Therefore, buffered channels only affect writes. Here's an example:

package main

import (
    "fmt"
)

func main() {
    var c = make(chan int, 3)
    c <- 1
    c <- 2
    c <- 3
    //c <- 4
    fmt.Println("end")
}

The output information is:

end

When writing to a channel with 3 buffers, since it is only written 3 times, the length of the channel is just equal to the length of the buffer, and the program is not blocked. When the comment before c <- 4 is removed, there is no program. To read this channel, the main program enters a deadlock state and causes an exception.

Coroutine communication

The channel type variable is essentially an address, as in the following sample code:

package main

import (
    "fmt"
)

func main() {
    var c = make(chan int, 3)
    fmt.Println(c)
}

Output result:

0xc042072080

Therefore, when the channel type variable is passed as a parameter to the function, the value in the channel can be directly modified in the function. Although the chan type variable is an address, golang does not allow the use of the value operator ( * ) to manipulate chan type variables. But if you first use the address operator (&) for the chan type variable and then use the value operator (*), this method works fine, but it doesn't make much sense unless your purpose is In the function call, redefine a chan type variable to replace the original variable.

These features of chan can be used to achieve synchronization between coroutines. A channel without buffering is a zero-tolerant wait that enables forced synchronization; a buffered channel has a certain amount of tolerance waiting, allowing synchronization with a certain time difference.

Simple example of inter-process communication:

package main

import (
    "fmt"
    "time"
)

func main() {
    var c = make(chan int)

    go func() {
        fmt.Println("Standby mode:")// Blocks when reading the channel, waiting for other coroutines to write information to the channelfmt.Println("The command code is: ", <-c)
    }()go func() {
        // Delay 3 seconds to write information to the channeltime.Sleep(time.Second * 3)
        fmt.Println("Send command:")
        c <- 8
        close(c)
    }()
    time.Sleep(time.Second * 5)
    fmt.Println("Execution completed")
}

The output information is:

Standby mode:
send command:
The command code is: 8
Execution completed