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:
maingoroutine startsa.fgoroutine.a.fblocks trying to read from the nil channela.exit.mainsetsa.exitto be an unbuffered channel,a.fis now blocked reading from the new channel, this is allowed.mainwrites a value intoa.exitanda.freads the value froma.exit, this synchronises the goroutines, nether are blocked now.a.fnow blocks trying to write into the unbuffereda.exit, this will never unblock because nobody will ever try to read from the channel again.mainnow 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.fgoroutine blocks ata.exit <- truebecause no other goroutine will read this value from the channel. - Your
maingoroutine will probably exit and terminate the entire program beforea.fcan 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
}
