魔女
发布于

Golang异常处理

Golang 中对于异常的处理通常是返回 Error 的形式。 假设我需要封装 http Response 返回,代码可能会是如下情况

type Header struct{
    Key,Value string
}
type Status struct{
    Code int
    Message string
}
func Response(w io.Writer,status Status, headers []Header, body io.Reader) error {
    _,err:=fmt.Fprintf(w, "HTTP/1.1 %d %s\r\n", status.Code,status.Message)
    if err!=nil{
        return err
    }
    for _,header:=range headers{
        _,err=fmt.Fprintf(w,"%s: %s\r\n",header.Key,header.Value)
        if err!=nil{
            return err
        }
    }
    _,err=fmt.Fprint(w,"\r\n")
    if err!=nil{
        return err
    }
    _,err=io.Copy(w,body)
    if err!=nil{
        return err
    }
    return nil
}

可以看到通篇都充斥着 if err!=null 的判断,看着很不优雅。 对于这种情况可以考虑用以下方式改变代码使其变得优雅。

type Header struct {
    Key, Value string
}
type Status struct {
    Code    int
    Message string
}
type errWriter struct {
    w   io.Writer
    err error
}

func (ew *errWriter) Write(bytes []byte) (int, error) {
    if ew.err != nil {
        return -1, ew.err
    }
    n,err:=ew.w.Write(bytes)
    ew.err=err
    return n,err
}

func Response(w io.Writer, status Status, headers []Header, body io.Reader) error {
    ew := &errWriter{w, nil}
    fmt.Fprintf(ew, "HTTP/1.1 %d %s\r\n", status.Code, status.Message)
    for _, header := range headers {
        fmt.Fprintf(ew, "%s: %s\r\n", header.Key, header.Value)
    }
    io.Copy(ew, body)
    return ew.err
}
评论