Go で Goroutine スタックトレースをダンプする

Jay Singh 2022年8月23日
Go で Goroutine スタックトレースをダンプする

奇妙な状況に対処するための慣用的なアプローチは、Go プログラムでエラーを使用することです。エラーは、ソフトウェアで発生する異常なケースの大部分を引き起こします。

ただし、まれに、異常な状態のためにソフトウェアを実行し続けることができない場合があります。この状況では、panic がプログラムを早期に終了する可能性があります。

関数が panic に遭遇すると、関数の実行は停止し、遅延した関数は実行され、制御は関数の呼び出し元に戻ります。

この手順は、現在のゴルーチンのすべての関数が戻るまで続きます。戻ると、プログラムは panic メッセージを出力し、次にスタックトレースを出力してから終了します。

サンプルプログラムを作成すると、これがより明確になります。

Go で panic を使用して Goroutine スタックトレースをダンプする

この簡単なスクリプトは、人のフルネームを出力します。fullName 関数は、個人の完全な名前を返します。

このメソッドは、firstName および lastName ポインターの nil 値をチェックします。nil の場合、関数はメッセージとともに panic シグナルを送信します。

プログラムが終了すると、このメッセージが出力されます。

package main

import (
    "fmt"
)

func fullName(firstName *string, lastName *string) {
    if firstName == nil {
        panic("runtime error: first name cannot be nil")
    }
    if lastName == nil {
        panic("runtime error: last name cannot be nil")
    }
    fmt.Printf("%s %s\n", *firstName, *lastName)
    fmt.Println("returned normally from fullName")
}

func main() {
    firstName := "Jay"
    fullName(&firstName, nil)
    fmt.Println("returned normally from main")
}

出力:

panic: runtime error: last name cannot be nil

goroutine 1 [running]:
main.fullName(0x405058?, 0xc000070f70?)
    /tmp/sandbox885911142/prog.go:12 +0x114
main.main()
    /tmp/sandbox885911142/prog.go:20 +0x35

次に、以下の例では、組み込みの len によって提供される長さを使用してスライスの最後の要素にアクセスしようとする一般的な間違いを犯しています。

これが panic を引き起こす理由を示すために、次のコードを実行します。

package main

import (
    "fmt"
)
func main() {
    names := []string{
        "Iron Man",
        "Thor",
    }
    fmt.Println("My favorite superhero is:", names[len(names)])
}

出力:

panic: runtime error: index out of range [2] with length 2

goroutine 1 [running]:
main.main()
    /tmp/sandbox2746930010/prog.go:12 +0x1b