如何在正确的情况下重构错误处理?

时间:2014-02-19 07:20:04

标签: go

我刚开始使用Go,所以我还不习惯它的模式。

我有一个Web服务器,可以作为其他远程服务的代理。我正在使用mux将路由映射到处理程序,这是使用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))
}

我想将公共代码(错误处理,转换为字符串和编写响应)重构为单个函数。

我的第一次尝试只是定义一个要调用的常用函数:

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())
}

但是

  1. 不起作用。我收到insufficient arguments错误。它可能与混合来自不直接转换为被调用函数的参数的服务的多个响应值有关。
  2. 我不喜欢传递错误参数的想法。也许那很好,它看起来很脏我。然后,我对Go还不太了解。
  3. 执行此操作的“正确方式”(或Go方式)是什么?

1 个答案:

答案 0 :(得分:4)

有一个blog post on golang.org about error handling专门讨论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))
}