Go 1.13までのゴルーチンの切り替えは、チャネルの送受信やシステムコール呼び出し、関数呼び出し前にコンパイラが暗黙的に挿入する処理などによって行われていました。そのため、上記の切り替わり操作を全く行わないループなどがあれば、そのゴルーチンがずっと実行されます。 func loop() { // この辺りにコンパイラがコード挿入している for { // 切り替わり処理が行われないので無限に実行される } } この結果、$GOMAXPROCSが1の場合はプログラムが停止します。コンパイラが挿入するコードは、インライン展開された場合やgo:nosplitディレクティブが記述された場合には行われないので、関数呼び出しをしていてもゴルーチンが切り替わらない場合はあります。 ゴルーチンの切り替えと関数のスタックチェック go doc compile/Compiler Directives Goの