golang http请求错误恐慌恢复

时间:2016-12-21 22:20:55

标签: http go request recover panic

我对golang编码相当新,并且正在为一个糟糕的网址请求而遇到恐慌/恢复过程。下面是一个查询URL列表并输出响应的脚本。有时会输入错误的URL或服务器关闭,HTTP请求失败会导致恐慌。我不清楚如何从中恢复并继续。我希望程序从恐慌中恢复,记录坏网址和错误,然后继续输出失败网址的网址列表和其他正常网址响应数据的错误。

package main

import (
    "fmt"
    "net/http"
)

var urls = []string{
    "http://www.google.com",        //good url, 200
    "http://www.googlegoogle.com/", //bad url
    "http://www.zoogle.com",        //500 example
}

//CONCURRENT HTTP REQUESTS -------------------------------------------
func MakeRequest(url string, ch chan<- string) {
    resp, err := http.Get(url)
    if err != nil {
        fmt.Println("Error Triggered", err)
        ch <- fmt.Sprintf("err: %s", err)
    }
    ch <- fmt.Sprintf("url: %s, status: %s ", url, resp.Status) // put response into a channel
    resp.Body.Close()
}

func main() {
    output := make([][]string, 0) //define an array to hold responses

    //PANIC RECOVER------------------------------
    defer func() { //catch or finally
        if r := recover(); r != nil { //catch
            fmt.Println("Recover Triggered: ", r)
        }
    }()

    //MAKE URL REQUESTS----------------------------------------------
    for _, url := range urls {
        ch := make(chan string)                 //create a channel for each request
        go MakeRequest(url, ch)                 //make concurrent http request
        output = append(output, []string{<-ch}) //append output to an array
    }

    //PRINT OUTPUT ----------------------
    for _, value := range output {
        fmt.Println(value)
    }
}

我正在寻找类似于:

的输出

[url:http://www.google.com,状态:200 OK]

[url:http://www.googlegoogle.com,错误:没有这样的主持人]

[url:http://www.zoogle.com,状态:500内部服务器错误]

2 个答案:

答案 0 :(得分:1)

谢谢Jim B.我认为恐慌是由请求触发的,但是尝试使用&#34; resp.Status&#34;对于失败的请求,因为它不存在。我修改了我的错误处理,只将resp.Status放在&#34; ch&#34;如果没有错误。如果出现错误,我会将不同的响应替换为&#34; ch&#34;带有错误值。没有必要恢复,因为没有引发恐慌。

func MakeRequest(url string, ch chan<- string) {
    resp, err := http.Get(url)
    if err != nil {
        ch <- fmt.Sprintf("url: %s, err: %s ", url, err)
    } else {
        ch <- fmt.Sprintf("url: %s, status: %s ", url, resp.Status) // put response into a channel
        defer resp.Body.Close()
    }
}

现在输出:

[url:http://www.google.com,状态:200 OK]

[url:http://www.googlegoogle.com/,错误:获取http://www.googlegoogle.com/:拨打tcp:查询www.googlegoogle.com:没有此类主机

[url:http://www.zoogle.com,状态:500内部服务器错误]

答案 1 :(得分:0)

我将(并且确实)恢复的唯一地方:在一个&#34;断层障碍&#34;。

A&#34;断层障碍&#34;是集中发现问题的最高可用地点。它通常是产生新goroutine的地方(即:每个http接受)。在ServeHTTP方法中,您可能希望捕获并记录单个恐慌而无需重新启动服务器(通常这种恐慌是微不足道的nil ptr derefs)。您可能会在无法检查您需要知道的情况的地方看到恢复 - 例如文件句柄是否已关闭。 (只是关闭并处理可能的恐慌)。

我有一个很大的代码库,只使用了恢复2或3次。它们仅适用于所提到的情况,我只是为了确保问题是专门记录的。我会做一个恢复只是为了记录消息,即使我还要去os.Exit并让我启动的脚本重启我。