Blocking problem of golang unbuffered channel

done:=make(chan struct{})
c:=make(chan int)
go func() {
    defer close(done)
    for{
        s,ok:=<-c
        if !ok{
            //close(c)
            return
        }
        println(s)
    }
}()
for i:=0;i<1 ;iPP  {
    println("put")
    c<-i
}
println("main....")
//close(c)
<-done

clipboard.png
formax+1BcloseA

clipboard.png

May.12,2021

you can close channel, in both places, except that the conditional statement below

        s,ok:=<-c
        if !ok{
            //close(c)
            return
        }

condition ! ok means that channel has been closed, and it is no longer meaningful to call close (c) at this time.
when channel is not closed, s, ok: = <-c enters a blocking state unless data arrives.

you can change it to this and exit the loop when there is no data

    for {
        select {
        case s, ok := <-c:
            if ok {
                println(s)
                continue
            }
            break
        default:  // channel 
            break
        }
    }

go func s code <-c in a for endless loop, the first loop blocks here, waiting for the c semaphore.
main the for loop prints out put , and then sends a c signal to the go func . The program receives this signal and starts execution. if! ok means false so return, go func will not print 0 at this time. Enter the next loop, still blocking and waiting for the c semaphore.
while main goes to println ("main.") , so it can print out main.

.
  1. if there is no area B close (c) , then the go func protocol blocks the waiting c semaphore, while the main protocol blocks the waiting down semaphore, resulting in lockout! , and the close (c) in area A does not have a chance to get there, so return, will not go to defer, and will not go to close (down)
  2. .
  3. if region B has close (c) , then the main protocol is temporarily blocked waiting for the down semaphore. go func receives this c semaphore and continues to go. At this time, c has already close, so if! ok for true, at this time, you can go to return, to jump out of the for dead cycle, go to the defer function, go to close (down), and send a down semaphore to main, at this time main continues to go, and complete the whole process.
Menu