Is there any API to let the main
goroutine sleep forever?
In other words, I want my project always run except when I stop it.
When we send data into the channel using a GoRoutine, it will be blocked until the data is consumed by another GoRoutine. When we receive data from channel using a GoRoutine, it will be blocked until the data is available in the channel.
So no, time. Sleep does not block the goroutine.
A goroutine is a function that executes simultaneously with other goroutines in a program and are lightweight threads managed by Go. A goroutine takes about 2kB of stack space to initialize.
The sleep method pauses the execution of the current thread temporarily. This type of task is important in many cases. In concurrent programming in Go, the sleep method is often used to block a thread temporarily and let other threads execute. It can also be used to simulate timeouts and create custom timers.
You can use numerous constructs that block forever without "eating" up your CPU.
For example a select
without any case
(and no default
):
select{}
Or receiving from a channel where nobody sends anything:
<-make(chan int)
Or receiving from a nil
channel also blocks forever:
<-(chan int)(nil)
Or sending on a nil
channel also blocks forever:
(chan int)(nil) <- 0
Or locking an already locked sync.Mutex
:
mu := sync.Mutex{}
mu.Lock()
mu.Lock()
If you do want to provide a way to quit, a simple channel can do it. Provide a quit
channel, and receive from it. When you want to quit, close the quit
channel as "a receive operation on a closed channel can always proceed immediately, yielding the element type's zero value after any previously sent values have been received".
var quit = make(chan struct{})
func main() {
// Startup code...
// Then blocking (waiting for quit signal):
<-quit
}
// And in another goroutine if you want to quit:
close(quit)
Note that issuing a close(quit)
may terminate your app at any time. Quoting from Spec: Program execution:
Program execution begins by initializing the main package and then invoking the function
main
. When that function invocation returns, the program exits. It does not wait for other (non-main
) goroutines to complete.
When close(quit)
is executed, the last statement of our main()
function can proceed which means the main
goroutine can return, so the program exits.
The above constructs block the goroutine, so if you don't have other goroutines running, that will cause a deadlock.
If you don't want to block the main
goroutine but you just don't want it to end, you may use a time.Sleep()
with a sufficiently large duration. The max duration value is
const maxDuration time.Duration = 1<<63 - 1
which is approximately 292 years.
time.Sleep(time.Duration(1<<63 - 1))
If you fear your app will run longer than 292 years, put the above sleep in an endless loop:
for {
time.Sleep(time.Duration(1<<63 - 1))
}
It depends on use cases to choose what kind of sleep you want.
@icza provides a good and simple solution for literally sleeping forever, but I want to give you some more sweets if you want your system could shutdown gracefully.
You could do something like this:
func mainloop() {
exitSignal := make(chan os.Signal)
signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM)
<-exitSignal
systemTeardown()
}
And in your main:
func main() {
systemStart()
mainloop()
}
In this way, you could not only ask your main to sleep forever, but you could do some graceful shutdown stuff after your code receives INT
or TERM
signal from OS, like ctrl+C
or kill
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With