文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
错误处理
Go 在错误处理上采用了与 C 类似的检查返回值的方式,而不是其他多数主流语言采用的异常方式,这造成了代码编写上的一个很大的缺点:错误处理代码的冗余,对于这种情况是通过复用检测函数来减少类似的代码。
请看下面这个例子代码:
func init() {
http.HandleFunc("/view", viewRecord)
}
func viewRecord(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
record := new(Record)
if err := datastore.Get(c, key, record); err != nil {
http.Error(w, err.Error(), 500)
return
}
if err := viewTemplate.Execute(w, record); err != nil {
http.Error(w, err.Error(), 500)
}
}
上面的例子中获取数据和模板展示调用时都有检测错误,当有错误发生时,调用了统一的处理函数 http.Error
,返回给客户端 500 错误码,并显示相应的错误数据。但是当越来越多的 HandleFunc
加入之后,这样的错误处理逻辑代码就会越来越多,其实可以通过自定义路由器来缩减代码
type appHandler func(http.ResponseWriter, *http.Request) error
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
http.Error(w, err.Error(), 500)
}
}
上面定义了自定义的路由器,然后可以通过如下方式来注册函数:
func init() {
http.Handle("/view", appHandler(viewRecord))
}
当请求 /view
的时候逻辑处理可以变成如下代码,和第一种实现方式相比较已经简单了很多。
func viewRecord(w http.ResponseWriter, r *http.Request) error {
c := appengine.NewContext(r)
key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
record := new(Record)
if err := datastore.Get(c, key, record); err != nil {
return err
}
return viewTemplate.Execute(w, record)
}
上面的例子错误处理的时候所有的错误返回给用户的都是 500 错误码,然后打印出来相应的错误代码,其实可以把这个错误信息定义的更加友好,调试的时候也方便定位问题,可以自定义返回的错误类型:
type appError struct {
Error error
Message string
Code int
}
这样自定义路由器可以改成如下方式:
type appHandler func(http.ResponseWriter, *http.Request) *appError
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if e := fn(w, r); e != nil { // e is *appError, not os.Error.
c := appengine.NewContext(r)
c.Errorf("%v", e.Error)
http.Error(w, e.Message, e.Code)
}
}
这样修改完自定义错误之后,逻辑处理可以改成如下方式:
func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
c := appengine.NewContext(r)
key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
record := new(Record)
if err := datastore.Get(c, key, record); err != nil {
return &appError{err, "Record not found", 404}
}
if err := viewTemplate.Execute(w, record); err != nil {
return &appError{err, "Can't display record", 500}
}
return nil
}
如上所示,在访问 view 的时候可以根据不同的情况获取不同的错误码和错误信息,虽然这个和第一个版本的代码量差不多,但是这个显示的错误更加明显,提示的错误信息更加友好,扩展性也比第一个更好。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论