Какие состояния могут быть у горутин в Go
Что проверяют
Представляете ли вы горутину как объект планировщика, а не просто «функцию с go впереди». Вопрос быстро уходит в модель GMP и в практику: как понять, что горутина висит, и где посмотреть её состояние. Следом часто спрашивают, что происходит с потоком ОС во время системного вызова.
Как отвечать
Состояния заданы в рантайме (runtime/runtime2.go) константами:
_Gidle: структура выделена, выполнение ещё не начиналось;_Grunnable: готова к работе, стоит в очереди и ждёт свободногоP;_Grunning: занимаетMиP, прямо сейчас исполняет код;_Gsyscall: внутри системного вызова, привязана кM, ноPу неё могут отобрать;_Gwaiting: заблокирована и в очередях планировщика не стоит, разбудит её тот, кто владеет причиной ожидания;_Gdead: отработала или ещё не запускалась, структура уходит в свободный список и переиспользуется;_Gcopystackи_Gpreempted: служебные, первое при росте стека, второе при асинхронной вытесняющей приостановке (появилась в Go 1.14).
Отдельно назовите waitReason: именно она видна в дампе как chan receive, select, sync.Mutex.Lock, IO wait, sleep. При разборе зависаний помогает именно она, а не список статусов.
Практическая часть: горутина на сетевом вводе-выводе уходит в _Gwaiting через netpoller и потока не занимает, а блокирующий системный вызов (файл, cgo) держит M целиком, и sysmon спустя десятки микросекунд отбирает у него P в пользу другого потока. Посмотреть состояния можно так: SIGQUIT по процессу для дампа стеков, профиль goroutine через net/http/pprof, GODEBUG=schedtrace=1000 для сводки по планировщику.
Где спотыкаются
Перечисляют выдуманные состояния вроде «создана» и «ожидающая» отдельно от _Gwaiting. Такого деления в рантайме нет, и вопрос про источник знаний становится неудобным.
Путают блокировку горутины с блокировкой потока. Чтение из пустого канала снимает горутину с процессора и почти ничего не стоит, а syscall.Read по файлу занимает поток целиком.
Не могут назвать ни одного способа посмотреть состояние в живом процессе. Без pprof и дампа по SIGQUIT знание списка констант выглядит заученным.