In Golang, channel is a very useful data structure that can safely pass data between coroutines. A channel can be closed to let the receiver know that all data has been delivered. However, in some cases, not closing the channel may be a better option.
First, let's look at why closing a channel might help. When we send data to a channel, it may be listened to by multiple coroutines at the same time. Here we have a simple example:
c := make(chan int) go func() { for i := 0; i < 10; i++ { c <- i } }() go func() { for i := range c { fmt.Println(i) } }()
Here we create a channel of type integer and start two coroutines. One coroutine sends the numbers 0 to 9 to the channel, while the other coroutine prints the data once it receives it.
When the sender completes sending, it should close the channel so that the receiver knows that all data has been transmitted. This can be accomplished by calling close(c)
when the sending coroutine has finished sending.
But what if a coroutine may not receive all the data? Maybe it has hung or been closed. In this case, closing the channel by the sender may cause the receiver to panic, causing the program to crash.
A solution to this problem might be to add a lock on the sender and release it when the receiver's coroutine completes. But this approach may make our code more complex and may reduce performance.
There is a better way, which is not to close the channel, but to use the features of the Go language to send additional elements on the channel to indicate that all data has been sent. This element can be of any type, usually we use nil or a specific tag.
Here's how to modify our sample code:
c := make(chan int) done := make(chan struct{}) go func() { for i := 0; i < 10; i++ { c <- i } done <- struct{}{} }() go func() { for { select { case i := <-c: fmt.Println(i) case <-done: return } } }()
Here we create a channel done
and send into it when the sender has finished sending a structure. The receiver's coroutine uses the select
statement to listen to two channels. Once it receives a signal from channel done
, it exits. This avoids the problem of channel closing while still providing a simple way to tell the receiver that all data has been sent.
In summary, closing the channel may cause some unnecessary trouble because it may cause the program to crash. In some cases, not closing the channel may be a better option. We can send additional elements on the channel to indicate that all data has been sent. This approach avoids the need for locks and makes the program simpler and more efficient.
The above is the detailed content of golang channel is not closed. For more information, please follow other related articles on the PHP Chinese website!