Есть ли какой-либо API, чтобы позволить main
goroutine спать навсегда?
Другими словами, я хочу, чтобы мой проект выполнялся всегда, за исключением случаев, когда я его останавливаю.
Есть ли какой-либо API, чтобы позволить main
goroutine спать навсегда?
Другими словами, я хочу, чтобы мой проект выполнялся всегда, за исключением случаев, когда я его останавливаю.
Вы можете использовать многочисленные конструкции, которые блокируются навсегда, не "съедая" ваш процессор.
Например, a select
без каких-либо case
(и no default
):
select{}
Или получение с канала, где никто ничего не отправляет:
<-make(chan int)
Или получение из канала nil
также блокируется навсегда:
<-(chan int)(nil)
Или отправка по каналу nil
также блокируется навсегда:
(chan int)(nil) <- 0
Или заблокировать уже заблокированный sync.Mutex
:
mux := sync.Mutex{}
mux.Lock()
mux.Lock()
Если вы хотите предоставить способ выхода, простой канал может это сделать. Предоставьте канал quit
и получите от него. Когда вы хотите выйти, закройте канал quit
, поскольку "операция приема на закрытом канале всегда может начинаться немедленно, давая тип элемента нулевое значение после любого ранее отправленного значения были получены".
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)
Обратите внимание, что выдача close(quit)
может прекратить ваше приложение в любое время. Цитата из Spec: Выполнение программы:
Выполнение программы начинается с инициализации основного пакета и последующего вызова функции
main
. Когда возвращается эта функция, программа завершает работу. Он не ждет завершения других (неmain
) goroutines.
Когда выполняется close(quit)
, может действовать последний оператор нашей функции main()
, что означает, что gotoutine main
может вернуться, поэтому программа завершает работу.
В зависимости от вариантов использования вы выбираете, какого сна вы хотите.
@icza предоставляет хорошее и простое решение для буквального спящего навсегда, но я хочу дать вам еще несколько сладостей, если вы хотите, чтобы ваша система могла законно прекратиться.
Вы можете сделать что-то вроде этого:
func mainloop() {
exitSignal := make(chan os.Signal)
signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM)
<-exitSignal
systemTeardown()
}
И в основном:
func main() {
systemStart()
mainloop()
}
Таким образом, вы можете не только просить ваш основной спать вечно, но вы можете сделать некоторые изящные выключения после того, как ваш код получит сигнал INT
или TERM
от ОС, например ctrl+C
или kill
.