Run the below example, you will see there was nothing printed from
fmt.Println
in exec()
, why?
func longexec (name) {
// simulate long execution
for p := 0; p < 10 ; p++ {
filled := strings.Repeat("=", p+1)
empty := strings.Repeat(" ", finish-p-1)
fmt.Printf("%s [%s%s]\n", name, filled, empty)
dur := time.Duration(rand.Intn(100))
time.Sleep(dur * time.Millisecond)
}
}
func main () {
go longexec("Thread 1")
go longexec("Thread 2")
}
The reason is, those 2 goroutines Thread 1
and Thread 2
didn't have enough
time to be executed because main()
was finished immediately after creating
them.
To give them time to execute, there're many ways, a common way is using channels. Receiving data from channels will be blocked until the sender side sends some data.
func exec (name, ch chan string) {
// simulate long execution
for p := 0; p < 10 ; p++ {
filled := strings.Repeat("=", p+1)
empty := strings.Repeat(" ", finish-p-1)
fmt.Printf("%s [%s%s]\n", name, filled, empty)
dur := time.Duration(rand.Intn(100))
time.Sleep(dur * time.Millisecond)
}
// notify this thread has finished
ch <- name
}
func main () {
ch := make(chan string)
go exec("Thread 1", ch)
go exec("Thread 2", ch)
fmt.Println('Finished', <- ch) // wait for the first finished thread
fmt.Println('Finished', <- ch) // wait for the second finished thread
}