13.Go言語異常メカニズム:panicとrecover

7359 ワード

プログラミング言語には一般的に異常捕獲メカニズムがあり、Pythonではraise文とtry-except文を用いて異常放出と異常捕獲を実現している.
Golangでは、構文エラーやタイプエラーなど、コンパイル段階で事前に警告できる通常のエラーが少なくありませんが、配列アクセスの限界、空のポインタ参照など、プログラムの実行後にのみ発生するエラーがあります.これらの実行時にエラーが発生すると、プログラムが終了します.
もちろん、プログラムダウンタイムの終了をトリガーできるのは、現在の環境がプログラムが行う予想条件に達していない場合(サービス指定のリスニングポートが他のプログラムに占有されている場合など)、手動でpanicをトリガーして、プログラムの終了を停止させることもできます.
1.panicをトリガーする
手動でダウンタイムをトリガーするのは、panicという内蔵関数を呼び出すだけで簡単です.
package main

func main() {
	panic("crash")
}

運転後、直接ダウンタイムを報告
$ go run main.go
go run main.go
panic: crash

goroutine 1 [running]:
main.main()
        E:/Go-Code/main.go:4 +0x40
exit status 2

2.キャプチャpanic
異常が発生した場合、Pythonのexceptのように捕獲されることがありますが、Golangではどのようにしてできますか?
これにより、ダウンタイムが発生した後にプログラムを再生させることができる別の組み込み関数であるrecoverを引き出さなければなりません.
しかしrecoverの使用には、defer関数で有効になる必要があり、他の役割ドメインでは動作しないという条件があります.
これは簡単な例です.
import "fmt"

func set_data(x int) {
	defer func() {
		// recover()        panic    
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	//         ,   panic
	var arr [10]int
	arr[x] = 88
}

func main() {
	set_data(20)

	//         ,  panic    
	//           
	fmt.Println("everything is ok")
}

運転後、出力は以下の通りです.
$ go run main.go
runtime error: index out of range [20] with length 10
everything is ok

通常、panicダウンタイムに入ったプログラムを処理するべきではありませんが、ダウンタイムからリカバリする必要がある場合があります.少なくとも、プログラムがクラッシュする前に、いくつかの操作を行うことができます.例えば、webサーバが予想できない深刻な問題に遭遇した場合、クラッシュする前にすべての接続を閉じる必要があります.処理をしないと、クライアントが待機状態になります.Webサーバがまだ開発段階にある場合、サーバは例外情報をクライアントにフィードバックし、デバッグを支援することもできます.
3.コンシステントを跨ぐことができない
上記の例から,panicがプログラム全体を終了させるとしても,終了する前にdefer遅延関数があればdeferを実行しなければならないことが分かる.
しかし,このdeferは複数のコヒーレンス間では効果がなく,サブコヒーレンスでpanicをトリガし,自分のコヒーレンス内のdeferのみをトリガし,mainコヒーレンス内のdefer関数を呼び出すことはできない.
実験をすればわかる
import (
	"fmt"
	"time"
)

func main() {
    //    defer      
	defer fmt.Println("in main")
    
	go func() {
		defer println("in goroutine")
		panic("")
	}()

	time.Sleep(2 * time.Second)
}

出力は次のとおりです.
in goroutine
panic:

goroutine 6 [running]:
main.main.func1()
        E:/Go-Code/main.go:12 +0x7b
created by main.main
        E:/Go-Code/main.go:10 +0xbc
exit status 2

4.まとめてみる
Golang異常の放出とキャプチャは、2つの内蔵関数に依存します.
  • panic:異常を投げ出し、プログラムをクラッシュさせる
  • recover:例外のキャプチャ、プログラムのリカバリ、または終了作業
  • revocer呼び出し後、投げ出されたpanicはここで終了し、これ以上投げ出されませんが、recoverは、任意に使用することはできません.強制的な要求があり、deferの下で使用しなければなりません.