package main
import (
"fmt"
)
type A struct{
exit chan bool
}
func (a *A) f(){
select{
//the routine process
//quit
case <- a.exit:
fmt.Println("-----over-----")
a.exit <- true
fmt.Println(" over ")
}
}
func main() {
a := A{}
go a.f()
a.exit = make(chan bool)
a.exit <- true
}
I'd like to run muti goroutines,and I want let the main func to notice other goroutine to quit. here is my code,but the program block in the select,the program only output "-----over-----",without " over ",what's wrong with the code?Grateful for your help.
CodePudding user response:
Your program blocks because that is what you have written, consider this order of operations:
main
goroutine startsa.f
goroutine.a.f
blocks trying to read from the nil channela.exit
.main
setsa.exit
to be an unbuffered channel,a.f
is now blocked reading from the new channel, this is allowed.main
writes a value intoa.exit
anda.f
reads the value froma.exit
, this synchronises the goroutines, nether are blocked now.a.f
now blocks trying to write into the unbuffereda.exit
, this will never unblock because nobody will ever try to read from the channel again.main
now exits and causes all other goroutines to exit, this might happen before step 5.
So the reasons your program never outputs over
are:
- Your
a.f
goroutine blocks ata.exit <- true
because no other goroutine will read this value from the channel. - Your
main
goroutine will probably exit and terminate the entire program beforea.f
can finish working.
I think you are asking how to make main exit after the goroutine is finished, this is the most simple example of that:
package main
import (
"fmt"
)
type A struct {
exit chan struct{}
}
func (a *A) f() {
defer close(a.exit) // Close the chanel after f() finishes, closed channels yield the zero-value so <-a.exit will unblock
fmt.Println(" over ")
}
func main() {
a := A{}
go a.f()
a.exit = make(chan struct{})
<-a.exit
}