golang for and select usage
In Golang, for and select are used quite commonly with each other. For example, the following code would continue to run at certain interval before it receive context cancellation request and terminates.
package main
import (
"context"
"fmt"
"time"
)
func main() {
// Create a parent context and a cancel function
ctx, cancel := context.WithCancel(context.Background())
// Start a goroutine that does some work
go doWork(ctx)
// Let it run for 3 seconds, then cancel
time.Sleep(3 * time.Second)
fmt.Println("Main: Cancelling the context...")
cancel() // This signals all goroutines using this context to stop
// Wait a bit to see the cancellation take effect
time.Sleep(1 * time.Second)
fmt.Println("Main: Done")
}
func doWork(ctx context.Context) {
for {
select {
case <-ctx.Done():
// Context was cancelled, exit gracefully
fmt.Println("Worker: Received cancellation signal, stopping...")
return
default:
// Do some work
fmt.Println("Worker: Working...")
time.Sleep(500 * time.Millisecond)
}
}
}
The output from here is,
Worker: Working... Worker: Working... Worker: Working... Worker: Working... Worker: Working... Worker: Working... Worker: Working... Main: Cancelling the context... Worker: Received cancellation signal, stopping... Main: Done
What will happen if we remove, for {} loop in there? Like so
package main
import (
"context"
"fmt"
"time"
)
func main() {
// Create a parent context and a cancel function
ctx, cancel := context.WithCancel(context.Background())
// Start a goroutine that does some work
go doWork(ctx)
// Let it run for 3 seconds, then cancel
time.Sleep(3 * time.Second)
fmt.Println("Main: Cancelling the context...")
cancel() // This signals all goroutines using this context to stop
// Wait a bit to see the cancellation take effect
time.Sleep(1 * time.Second)
fmt.Println("Main: Done")
}
func doWork(ctx context.Context) {
//for {
select {
case <-ctx.Done():
// Context was cancelled, exit gracefully
fmt.Println("Worker: Received cancellation signal, stopping...")
return
default:
// Do some work
fmt.Println("Worker: Working...")
time.Sleep(500 * time.Millisecond)
}
//}
}
The goroutine would stop checking for context done and do the defaults. It will be a sequential execution where main thread call goroutine, goroutine outputs the message. Then main thread waits for 3 seconds and then send cancellation. So the output looks something like this.
Worker: Working... Main: Cancelling the context... Main: Done
Comments