• 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) } }
  • 相关阅读:
    如何理解C语言的左结合 和右结合性
    Egg项目使用vscode的debug模式跑单元测试
    为什么要用MongoDB副本集
    理解JS原型和原型链
    防止重复请求攻击
    引擎、编译器和作用域
    闭包原理解析及其应用场景
    树形结构数据完美解决方案
    Excel文件导入导出(基于Nodejs、exceljs)
    架构层面高并发解决方案选择----项目架构模式选择
  • 原文地址:https://www.cnblogs.com/vincenshen/p/9318015.html
Copyright © 2020-2023  润新知