question
Go two coroutines use the same file handle, one of which closes the file handle and exits the coroutine. How to promptly notify the other coroutine to exit?
analyze
When a coroutine closes this file object, the file descriptor of the underlying file is released.
At this time, another coroutine still holds the same file object, but the corresponding file descriptor no longer exists.
Therefore, when the second coroutine operates on the file through this file object, such as reading and writing files, an exception will occur, such as no error in the file descriptor.
solve
To avoid this problem, multiple coroutines that share file objects need to be coordinated through a channel or lock:
Each coroutine needs to obtain a lock or receive notifications from the channel before using the file object.
Finally, after closing the coroutine that closes the file object, the coroutine object is notified through channel or unlocking to notify other coroutine objects that are invalid.
After other coroutines receive notification, they no longer operate on this closed file object.
1. Use channel channel
In the main coroutine, a channel can be defined to notify other coroutines to exit. The coroutine can listen to this channel when it is executed. Once the exit notification is received, it can clean up and exit the coroutine.
quit := make(chan bool) go func() { defer ("Goroutine exit") for { select { case <-quit: return default: // ... } } }() // Send an exit notification in the main coroutinequit <- true
2. Use the context package
The Go language standard library provides context packages that can be used to control the life cycle of coroutines.
In the main coroutine, you can create a context object and pass it to the coroutine, and then call the cancel method to notify all coroutines to exit.
() is an important initial predefined context value in the Go context system, representing an empty context environment without a deadline limit.
1. Create context and cancel functions using WithCancel function
ctx, cancel := (()) go func(ctx ) { for { select { case <-(): ("exit") return default: // Perform some time-consuming operations (1 * ) ("running") } } }(ctx) (5 * ) // cancel() ("cancelled") (1 * )
2. Use Deadline to end the coroutine
ctx, cancel := ((), ().Add())
3. Use WithTimeout to limit the operation time
ctx, cancel := ((), )
The above is the detailed explanation of the example of Go using chan or context to exit coroutine. For more information about Go chan context to exit coroutine, please follow my other related articles!