golang channel type

1. What is a channel type?

    Channels in the Go language are a special type. A channel is like a conveyor belt or queue, always following 先入先出the (First In First Out) rule to ensure the order of sending and receiving data. Each channel is a conduit of a specific type, that is, when declaring a channel, you need to specify its element type.

    If goroutine is the concurrent execution body of the Go program, channel is the connection between them. A channel is a communication mechanism that allows one goroutine to send specific values ​​to another goroutine.

2. Reasons for the creation of channels

    Although shared memory can be used for data exchange, shared memory is prone to problems in different goroutines 竞态. In order to ensure the correctness of data exchange, a mutex must be used to lock the memory. This approach will inevitably cause performance problems.

    The concurrency model of Go language is CSP (Communicating Sequential Processes), which advocates 通信共享内存communication through shared memory rather than through shared memory.

3. Declare channel

grammar:


var 变量 chan 元素类型  

example:


var ch1 chan int   // 声明一个传递整型的通道
var ch2 chan bool  // 声明一个传递布尔型的通道
var ch3 chan []int // 声明一个传递int切片的通道   
    

4. Create channel

grammar:


make(chan 元素类型, [缓冲大小])  
 

Note: The declared channel needs to be initialized using the make function before it can be used. The buffer size of the channel is optional.

example:


ch4 := make(chan int, 3)
ch5 := make(chan bool)
ch6 := make(chan []int)   

5. Channel related operations

1. Send value

Send a value to the channel.

example:


ch <- 10 // 把10发送到ch中   

2. Receive value

Receives a value from a channel.

example:


x := <- ch // 从ch中接收值并赋值给变量x
<-ch       // 从ch中接收值,忽略结果   

3. Close the channel

example:


close(ch)   

3.1 Note

    The channel only needs to be closed when the receiving goroutine is notified that all data is available 发送完毕. The channel can be 垃圾回收机制recycled, which is different from closing the file. Closing the file must be done after the operation is completed, but closing the channel is not the same 不是必须.

3.2 Features

  1. Sending a value to a closed channel will cause a panic.
  2. Receiving on a closed channel will keep getting values ​​until the channel is empty.
  3. A receive operation on a closed channel with no value will result in a zero value of the corresponding type.
  4. Closing an already closed channel will cause panic.

4. Channel type

1. No buffer channel

    Unbuffered channels can only send values ​​when someone receives them. Just like there are no express lockers or collection points in the community where you live, the courier must deliver the item to you when he calls you. To put it simply, it is an unbuffered channel 必须有接收才能发送.

Insert image description here

grammar:


ch := make(chan type) 

example:


func recv(c chan int) {
    
    
    ret := <-c
    fmt.Println("接收成功", ret)
}
func main() {
    
    
    ch := make(chan int)
    go recv(ch) // 启用goroutine从通道接收值
    ch <- 10
    fmt.Println("发送成功")
}  
 

Analysis: The send operation on the unbuffered channel will block until another goroutine performs a receive operation on the channel. At this time, the value can be sent successfully, and the two goroutines will continue to execute. Conversely, if the receive operation is executed first, the receiving goroutine will block until another goroutine sends a value on the channel.

2. There is a buffer channel

    As long as the capacity of the channel is greater than zero, then the channel is a buffered channel, and the capacity of the channel represents the number of elements that can be stored in the channel. Just like the express cabinet in your community only has so many compartments. When the compartments are full, they can't fit in and become blocked. When someone else takes it away, a courier can put one in there.

Insert image description here
grammar:


ch := make(chan type, [cap]) 

example:


func main() {
    
    
    ch := make(chan int, 1) // 创建一个容量为1的有缓冲区通道
    ch <- 10
    fmt.Println("发送成功")
}   
 

5. One-way channel

    Sometimes we pass channels as parameters between multiple task functions. Many times when we use channels in different task functions, we will restrict them. For example, restricting channels to only send or only receive in functions.

grammar:


chan<- int  是一个只能发送的通道,可以发送但是不能接收;
<-chan int  是一个只能接收的通道,可以接收但是不能发送。

example:


func counter(out chan<- int) {
    
    
    for i := 0; i < 100; i++ {
    
    
        out <- i
    }
    close(out)
}

func squarer(out chan<- int, in <-chan int) {
    
    
    for i := range in {
    
    
        out <- i * i
    }
    close(out)
}
func printer(in <-chan int) {
    
    
    for i := range in {
    
    
        fmt.Println(i)
    }
}

func main() {
    
    
    ch1 := make(chan int)
    ch2 := make(chan int)
    go counter(ch1)
    go squarer(ch2, ch1)
    printer(ch2)
}     
 

Note: It is possible to convert a two-way channel into a one-way channel during function parameter passing and any assignment operation, but not the other way around.

6. Loop values ​​from channels

example:


// channel 练习
func main() {
    
    
    ch1 := make(chan int)
    ch2 := make(chan int)
    // 开启goroutine将0~100的数发送到ch1中
    go func() {
    
    
        for i := 0; i < 100; i++ {
    
    
            ch1 <- i
        }
        close(ch1)
    }()
    // 开启goroutine从ch1中接收值,并将该值的平方发送到ch2中
    go func() {
    
    
        for {
    
    
            i, ok := <-ch1 // 通道关闭后再取值ok=false
            if !ok {
    
    
                break
            }
            ch2 <- i * i
        }
        close(ch2)
    }()
    // 在主goroutine中从ch2中接收值打印
    for i := range ch2 {
    
     // 通道关闭后会退出for range循环
        fmt.Println(i)
    }
}   

Analysis: There are two ways to determine whether the channel is closed when receiving a value. We usually use the for range method.

おすすめ

転載: blog.csdn.net/change_any_time/article/details/128978799