15.5. 让 Web 应用更加健壮

未匹配的标注

当 web 服务器发生一个恐慌( panic )时,我们的 web 服务器就会终止。这样非常的糟糕:一个 web 服务必须是一个健壮的程序,能够处理可能会出现的问题。

一个方法是可以在每一个处理函数( handler )中去使用 defer/recover ,但是这样会导致出现很多重复的代码。更加优雅的解决方法是使用 13.5 章节 中的闭包的方法处理错误。我们将这种机制应用到上一节中的 simple webserver 中,当然,它也可以很容易的应用于任何 web 服务器的程序中。

为了使代码更具可读性,我们为处理函数(HandleFunc)创建一个 type :

type HandleFnc func(http.ResponseWriter,*http.Request)

我们模仿 13.5 章节 的 errorHandler 函数,创建一个 logPanics 函数:

func logPanics(function HandleFnc) HandleFnc {
    return func(writer http.ResponseWriter, request *http.Request) {

        defer func() {

            if x := recover(); x != nil {

                log.Printf("[%v] caught panic: %v", request.RemoteAddr, x)

            }

        }()

    function(writer, request)

    }

}

然后我将处理函数作为回调包装进 logPanics:

http.HandleFunc("/test1", logPanics(SimpleServer))

http.HandleFunc("/test2", logPanics(FormServer))

处理函数中应该包含一个 panic 的调用,或者像 [1.3 章节] 中的用来检查错误的 check(error) 函数;下面是完整的代码示例:

译者注:可以在 SimpleServer 中直接写一个 panic(errors.New(“test error”)) 来模拟出现 panic

Listing 15.11—robust_webserver.go:

package main

import (

    "net/http"

    "io"

    "log"

)

type HandleFnc func(http.ResponseWriter,*http.Request)

// 将上一章节示例 15.10 中的代码复制过来,除了 main() 函数都复制过来

func main() {

    http.HandleFunc("/test1", logPanics(SimpleServer))

    http.HandleFunc("/test2", logPanics(FormServer))

    if err := http.ListenAndServe(":8088", nil); err != nil {

        panic(err)

    }

}

func logPanics(function HandleFnc) HandleFnc {

    return func(writer http.ResponseWriter, request *http.Request) {
        defer func() {

            if x := recover(); x != nil {

                log.Printf("[%v] caught panic: %v", request.RemoteAddr, x)

                // 下面一行代码是译者添加,默认出现 panic 只会记录日志,页面就是一个无任何输出的白页面,
                // 可以给页面一个错误信息,如下面的示例返回了一个 500
                http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)

            }

        }()

        function(writer, request)

    }

}

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/the-way-to-go/1...

译文地址:https://learnku.com/docs/the-way-to-go/1...

上一篇 下一篇
贡献者:2
讨论数量: 0
发起讨论 查看所有版本


暂无话题~