GO言語Error処理

3793 ワード

Go言語ではJava,C#,Python言語のようなtry...catch異常処理は提供されず,関数の戻り値によって階層的に投げ出される.メリットは、処理すべきエラーを漏らさないことです.悪いところはコードがうるさいことです.
エラーと例外の違い
エラーとは、ファイルを開くのに失敗したなど、問題が発生する可能性がある場所に問題が発生したことを意味します.異常は、空のポインタなど、問題が発生してはいけない場所に問題が発生したことです.Goのエラーは一種のタイプであり,エラーは内蔵errorタイプ(インタフェース)で表される.エラーは変数に格納され、関数から返されます.
type error interface {
    Error() string
}

カスタムエラーの作成
カスタムエラーを作成するには、errorsパッケージのNew()関数とfmtパッケージのErrorf()関数を使用します.
//    error   
    err1 := errors.New("    ...")
    fmt.Println(err1)
    fmt.Printf("%T
", err1) //*errors.fundamental // error err2 := fmt.Errorf(" :%d", 10000) fmt.Println(err2) // :10000 fmt.Printf("%T
", err2) //*errors.errorString

カスタムエラーの例
//     
type areaError struct {
    msg    string  //    
    length float64 //    
    wigth  float64 //    
}

func (e *areaError) Error() string {
    return e.msg
}
func (e *areaError) lengthNegative() bool {
    return e.length < 0 //   0 ,  false
}
func (e *areaError) wigthNegative() bool {
    return e.wigth < 0 //   0 ,  false
}
func revArea(length, wigth float64) (float64, error) {
    msg := ""
    if length < 0 {
        msg = "    0"
    }
    if wigth < 0 {
        if msg == "" {
            msg = "    0"
        } else {
            msg += ",    0"
        }
    }
    if msg != "" {
        return 0, &areaError{msg, length, wigth}
    }
    return length * wigth, nil
}
func main() {
    length, wigth := -4.3, -6.7
    area, err := revArea(length, wigth)
    if err != nil {
        fmt.Println(err)
        //      error
        if err, ok := err.(*areaError); ok {
            if err.lengthNegative() {
                fmt.Printf("error:  ,%.2f  0
", err.length) } if err.wigthNegative() { fmt.Printf("error: ,%.2f 0
", err.wigth) } } return } fmt.Println(" :", area) } : 0, 0 error: ,-4.30 0 error: ,-6.70 0

panic/recover
GOはpanic/recoverモードを使用してエラーを処理できます.panicはどこでも開始できますが、recoverはdefer呼び出しの関数でのみ有効です.defer文を含む関数が実行されるまで、遅延関数(defer後の関数)は実行されません.defer文を含む関数がreturnの正常な終了によっても、panicによる異常な終了にかかわらず、1つの関数で複数のdefer文を実行できます.これらの実行順序は宣言順序とは逆です.
panic:
  • 内蔵関数
  • 関数Fにpanic文が書かれている場合、その後実行するコードは終了し、panicが存在する関数F内に実行するdefer関数のリストがある場合はdeferの逆順で
  • を実行する.
  • は、関数Fの呼び出し元Gを返し、Gでは、関数F文が呼び出された後のコードは実行されません.関数Gに実行するdefer関数のリストがある場合、defertの逆順序で実行されます.ここでのdeferはtry-catch-finallyのfinally
  • に似ています.
  • goroutine全体が終了するまで、エラー
  • が報告されます.
    recover
  • 内蔵関数
  • goroutineのpanicking動作を制御し、panicをキャプチャし、アプリケーションの動作に影響を与えるために使用される
  • 一般的な呼び出し推奨:defer関数では、receverによってgoroutineのpanickingプロセスを終了し、正常なコードの実行を回復する.panicを介して伝達されるerrorを取得することができる簡単に言えばgoではpanicの異常を放出することができ、deferでrecoverを介してこの異常を捕獲し、正常に処理することができる.
    ≪インスタンス|Instance|emdw≫
    func a()  {
        fmt.Println("func a")
    }
    func b()  {
        panic("func b")
    }
    func c()  {
        fmt.Println("func c")
    }
    func main()  {
        a()
        b()
        c()
    }
    

    func bに実行すると例外が投げ出され、プログラムがクラッシュし、recoverを使用してプログラムをリカバリできます.
    func a()  {
        fmt.Println("func a")
    }
    func b()  {
        defer func() {
            err := recover()
            if err != nil{
                fmt.Println("recover fun b")
            }
        }()
        panic("func b")
    }
    func c()  {
        fmt.Println("func c")
    }
    func main()  {
        a() //func a
        b() //recover fun b
        c() //func c
    }
    
  • recover()はdeferと組み合わせて使用する必要があります.
  • deferは、panicを開始する可能性のある文の前に定義する必要があります.

  • 転載先:https://www.cnblogs.com/aresxin/p/GO-Error.html