go的标准化error处理

发布于:2024-04-17 ⋅ 阅读:(18) ⋅ 点赞:(0)

go的标准化error处理

1、建议这样写错误处理

// 1
func autn() {
	var err error
	if err != nil {
		// handle err
	}
	//do stuff
}

// 2 
func a(r *http.Request) error {
	//err := r.ParseForm()
	//if err != nil {
	//	return err
	//}
	//return nil
	// 我们其实没有必要写这么多的代码,直接返回就可以了
	return r.ParseForm()
	// 这样用也可能造成递归的返回错误直到最上层也是原始的错误

	// 在处理错误的时候我们应该只做一个决定就是:记录日志或返回错误
	// 返回错误的时候尽量以 errors.New("包名:错误原因“) 的形式
}

2、怎么优化代码让其不再堆积

优化前:我们可以看到有4个地方都需要进行错误判断,我们可以想办法将所有的错误处理代码写到别的地方,进行调用即可。

type Header struct {
	Key, Value string
}
type Status struct {
	Code   int
	Reason string
}

func WriteResponse(w io.Writer, status Status, headers []Header, body io.Reader) error {
	_, err := fmt.Fprintf(w, "%d %s\r\n", status.Code, status.Reason)
	if err != nil {
		return err // 1
	}
	for _, h := range headers {
		_, err := fmt.Fprintf(w, "%s:%s\r\n", h.Key, h.Value)
		if err != nil {
			return err // 2
		}
	}
	_, err = fmt.Fprint(w, "\r\n")
	if err != nil {
		return err // 3
	}
	_, err = io.Copy(w, body)
	return err // 4
}

优化后:

type errWriter struct {
	w   io.Writer
	err error
}

// 把判断错误的一些细节放到errWriter里面去
func (ew *errWriter) Write(p []byte) (int, error) {
	if ew.err != nil {
		return 0, ew.err
	}
	var n, err = ew.w.Write(p)
	if err != nil {
		ew.err = err
	}
	return n, nil
}

func WriteResponse1(w io.Writer, status Status, headers []Header, body io.Reader) error {
	ew := &errWriter{w: w}
	fmt.Fprintf(ew, "%d %s\r\n", status.Code, status.Reason)
	for _, h := range headers {
		fmt.Fprintf(ew, "%s:%s\r\n", h.Key, h.Value)
	}
	fmt.Fprint(ew, "\r\n")
	io.Copy(ew, body)
	return ew.err
}