Различные жесты блокировки навсегда в Голанге
Текущий дизайн среды выполнения Go предполагает, что сам программист отвечает за определение момента завершения горутины и завершения программы. Программу можно завершить обычным способом, вызвав os.Exit или вернувшись из функции main(). А иногда нам нужно сделать программный блок на этой строке.
Используйте sync.WaitGroup
Подождите, пока WaitGroup не станет равным 0
package main
import "sync"
func main() {
var wg sync.WaitGroup
wg.Add(1)
wg.Wait()
}
пустой выбор
select{} — это выборка без регистра, она всегда будет блокироваться
package main
func main() {
select{}
}
бесконечный цикл
Хотя он может блокироваться, он будет занимать 100% ЦП. Не рекомендуется для использования
package main
func main() {
for {}
}
с sync.Mutex
Блокировка, которая уже была заблокирована, будет заблокирована навсегда, если она будет заблокирована снова.Это не рекомендуется.
package main
import "sync"
func main() {
var m sync.Mutex
m.Lock()
m.Lock()
}
os.Signal
Системный семафор, который также является активным каналом, блокируется до тех пор, пока не будет получено определенное сообщение.
package main
import (
"os"
"syscall"
"os/signal"
)
func main() {
sig := make(chan os.Signal, 2)
signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT)
<-sig
}
Пустой канал или нулевой канал
Канал будет заблокирован до тех пор, пока не будет получено сообщение, а нулевой канал будет заблокирован навсегда.
package main
func main() {
c := make(chan struct{})
<-c
}
package main
func main() {
var c chan struct{} //nil channel
<-c
}
Суммировать
Обратите внимание, что большая часть кода, написанного выше, не может быть запущена напрямую и будет вызывать панику с сообщением «все горутины спят — тупик!», потому что среда выполнения go проверит, что все ваши горутины зависли, и ни одну из них не нужно выполнять. . Вы можете добавить перед блокирующим кодом одну или несколько горутин собственной бизнес-логики, чтобы не было взаимоблокировки.