您的位置:首页 > 编程语言 > Go语言

Go语言中统一异常处理实现方式

2018-05-21 18:12 721 查看

主要讲解Go语言中统一异常处理

Go语言和其他语言一样,为了提升程序可读性和业务分离,应该将错误处理单独抽取出来形成一个独立的模块,弱化在业务处理时对错误的频繁判断处理

主要知识点:

熟悉统一错误处理的方式

error 和 panic ,能自己识别到的错误就用error,panic是一种碰到错误终止程序的错误,能不用尽量不用

一般使用 defer + panic + recover 结合进行统一错误处理

使用 Type Assertion 判断错误类型

结合函数式编程实现

以下通过代码实现统一异常处理,代码示例为查看当前目录下文件内容,开启Web服务器,请求连接为:http://localhost:8888/list/abc.txt

可对请求 URL进行验证,地址中 /list/ 是否存在,文件是否存在,是否具有可读权限等。

具体代码如下:

package main

import (
"log"
"net/http"
_ "net/http/pprof"
"os"
"fmt"
"strings"
"io/ioutil"
)

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 {
fmt.Println()
//判断 请求 URL 必须以 prefix 开头
if strings.Index(
request.URL.Path, prefix) != 0 {
return userError(
fmt.Sprintf("path %s must start "+"with %s",
request.URL.Path, prefix))
}
path := request.URL.Path[len(prefix):]
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()

all, err := ioutil.ReadAll(file)
if err != nil {
return err
}

writer.Write(all)
return nil
}

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

//定义一个个错误统一处理方法
func errWrapper(handler appHandler) func(http.ResponseWriter, *http.Request) {
//闭包
return func(writer http.ResponseWriter,request *http.Request) {
// 如果 发现 panic,判断错误输出错误,否则 继续往上层 panic
defer func() {
if r := recover(); r != nil {
log.Printf("Panic: %v", r)
http.Error(
writer, //向writer汇报错误
http.StatusText(http.StatusInternalServerError), //错误描述信息(字符串)
http.StatusInternalServerError) //系统内部错误
}
}()
// 执行业务代码操作,上面定义的 defer 就是防止 业务代码中出现 panic
err := handler(writer, request)

// 如果业务代码执行出错
if err != nil {
//日志输出错误信息
log.Printf("Error occurred handling request: %s",err.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 //其他错误
}
//向writer 中写入错误信息
http.Error(writer,http.StatusText(code), code)
}
}
}

//type userError interface {
//	error
//	Message() string
//}

func main() {
//为 http服务 "/" 请求 增加 处理方法
http.HandleFunc("/",errWrapper(HandleFileList))

err := http.ListenAndServe(":8888", nil)
if err != nil {
panic(err)
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Go