英文:
How to refactor error handling in go properly?
问题
我刚开始学习Go语言,所以还不习惯它的模式。
我有一个作为代理的Web服务器,用于访问其他远程服务。我正在使用mux
将路由映射到处理程序,代码是在App Engine上运行的。
// imports omitted.
func init() {
m = mux.NewRouter()
m.HandleFunc("/ponies", listPonies)
m.HandleFunc("/rainbows", listRainbows)
http.Handle("/", m)
}
func listPonies(w http.ResponseWriter, r *http.Request) {
ponies, err := ponyService.getAll()
if err != nil {
w.write(err.Error())
return;
}
w.write(string(ponies))
}
func listRainbows(w http.ResponseWriter, r *http.Request) {
rainbows, err := rainbowService.getAll()
if err != nil {
w.write(err.Error())
return;
}
w.write(string(rainbows))
}
我想将通用代码(错误处理、转换为字符串和写入响应)重构为一个单独的函数。
我的第一次尝试是简单地定义一个通用函数来调用:
func handleErrorAndWriteResponse(w http.ResponseWriter, obj Stringer, err error) {
if err != nil {
w.write(err.Error())
return;
}
w.write(string(obj))
}
然后像这样调用它:
func listPonies(w http.ResponseWriter, r *http.Request) {
handleErrorAndWriteResponse(w, ponyService.getAll())
}
func listRainbows(w http.ResponseWriter, r *http.Request) {
handleErrorAndWriteResponse(w, rainbowService.getAll())
}
但是:
- 它不起作用。我得到一个
insufficient arguments
错误。这可能与混合使用多个服务的多个响应值,而这些值不能直接转换为被调用函数的参数有关。 - 我不喜欢传递错误参数的想法。也许这没问题,只是看起来有点乱。不过,我对Go还不太了解。
有没有什么“正确的方法”(或者说Go的方法)来做到这一点呢?
英文:
I'm just starting with Go so I'm still not used to its patterns.
I have a web server that serves as a proxy to other remote services. I'm using mux
to map routes to handlers, the code it's using App Engine.
// imports ommited.
func init() {
m = mux.NewRouter()
m.HandleFunc("/ponies", listPonies)
m.HandleFunc("/rainbows", listRainbows)
http.Handle("/", m)
}
func listPonies(w http.ResponseWriter, r *http.Request) {
ponies, err := ponyService.getAll()
if err != nil {
w.write(err.Error())
return;
}
w.write(string(ponies))
}
func listRainbows(w http.ResponseWriter, r *http.Request) {
rainbows, err := rainbowService.getAll()
if err != nil {
w.write(err.Error())
return;
}
w.write(string(rainbows))
}
I would like to refactor the common code (error handling, converting to string and writing the response) into a single function.
My first attempt was simply defining a common function to call:
func handleErrorAndWriteResponse(w http.ResponseWriter, obj Stringer, err error) {
if err != nil {
w.write(err.Error())
return;
}
w.write(string(obj))
}
And call it like this
func listPonies(w http.ResponseWriter, r *http.Request) {
handleErrorAndWriteResponse(w, ponyService.getAll())
}
func listRainbows(w http.ResponseWriter, r *http.Request) {
handleErrorAndWriteResponse(w, rainbowService.getAll())
}
But
- It doesn't work. I get an
insufficient arguments
error. It probably has to do with mixing the multiple response values from the services that don't translate directly into arguments of the function called. - I don't like the idea of passing the error arguments around. Maybe that's fine, it just looks dirty to me. Then again, I don't know much about Go yet.
What's the "right way" (or the Go way) to do this?
答案1
得分: 4
有一篇关于在AppEngine应用程序中处理错误的博客文章,详细介绍了错误处理。特别是要查看“简化重复错误处理”部分。
处理错误的方法基本上是让处理函数在失败的情况下返回一个error
,然后用通用的错误处理程序包装对它们的调用:
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 listPonies(w http.ResponseWriter, r *http.Request) error {
ponies, err := ponyService.getAll()
if err != nil {
return err;
}
w.write(string(ponies))
}
你还需要以不同的方式注册你的处理程序:
func init() {
http.Handle("/view", appHandler(listPonies))
}
英文:
There is an blog post on golang.org about error handling that specifically talks about error handling in an AppEngine application. Specifically, check out the "Simplifying repetitive error handling" section.
The way to do error handling is basically to let your handle functions return an error
in case they fail and then wrap the call to them with the common error handler:
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 listPonies(w http.ResponseWriter, r *http.Request) error {
ponies, err := ponyService.getAll()
if err != nil {
return err;
}
w.write(string(ponies))
}
You would also need to register your handlers differently:
func init() {
http.Handle("/view", appHandler(listPonies))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论