Go panic recover

panic

1. 停止当前函数执行

2. 一直向上返回,执行每一层的defer

3. 如果没有遇到recover, 程序退出

recover

1. 仅在defer调用中使用

2. 获取panic的值

3. 如果无法处理,可重新panic

示例1

package main

import (
"errors"
"fmt"
)

func tryRecover() {
    defer func() {
        r := recover()
        // r.(type) 判断对象的类型
        if err, ok := r.(error); ok {
            fmt.Println("Error occurred:", err)
        } else {
            panic(r)
        }
    }()
    panic(errors.New("this is an error"))
}

func main() {
    tryRecover()
}

示例2: 处理Web Error

errorHandler.go

package filelisting

import (
    "net/http"
    "os"
    "io/ioutil"
    "strings"
)

const prefix = "/list/"

type userError string

func (e userError) Error() string {
    return e.Message()
}

func (e userError) Message() string {
    return string(e)
}

func HandleFileList(writer http.ResponseWriter, request *http.Request) error {
    index := strings.Index(request.URL.Path, prefix)
    if index != 0 {
        return userError("path must start with " + prefix)
    }
    path := request.URL.Path[len(prefix):]
    file, err := os.Open(path)
    if err != nil {
        return err
    }
    defer file.Close()
    bytes, err := ioutil.ReadAll(file)
    if err != nil {
        return err
    }
    writer.Write(bytes)
    return nil
}

web.go

package main

import (
    "net/http"
    "imooc/errhanding/filelistingserver/filelisting"
    "os"
    "log"
)

type appHandler func(writer http.ResponseWriter, request *http.Request) error

// error装饰器 func errWrapper(handler appHandler) func(writer http.ResponseWriter, request
*http.Request) { return func(writer http.ResponseWriter, request *http.Request) { defer func() { if r := recover(); r != nil { log.Println("Panic: ", r) http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } }() err := handler(writer, request) if err != nil { logger := log.New(os.Stdout, "[Warn]", log.Lshortfile) logger.Printf("Error handling request: %s", err.Error()) // 自定义user error... if userErr, ok := err.(userError); ok { http.Error(writer, userErr.Message(), http.StatusBadRequest) return } code := http.StatusOK switch { case os.IsNotExist(err): code = http.StatusNotFound case os.IsPermission(err): code = http.StatusForbidden default: code = http.StatusInternalServerError } http.Error(writer, http.StatusText(code), code) } } } type userError interface { error Message() string } func main() { http.HandleFunc("/", errWrapper(filelisting.HandleFileList)) err := http.ListenAndServe(":8888", nil) if err != nil { panic(err) } }

猜你喜欢

转载自www.cnblogs.com/vincenshen/p/9318015.html