如何正确处理Golang中的网络错误

huangapple go评论80阅读模式
英文:

How to handle net errors in golang properly

问题

我不明白如何处理从net包接收到的错误。我需要知道发生了什么类型的错误才能进行下一步操作。尝试解析错误消息字符串可能不是正确的方法...

response, err := data.httpClient.Get("https://" + domain)
if err != nil {				
    fmt.Println("[!] error: ", err)
    /* 
    *  我想要类似伪代码的东西:
    *  if error == DnsLookupError {
    *      action1()
    *  } else if error == TlsCertificateError {
    *      action2()
    *  } else if error == Timeout {
    *      action3()
    *  } ...
    */
}

我收到的错误消息示例:

Get "https://example1.com": 远程错误: tls: 内部错误
Get "https://example2.com": 拨号tcp: 查找example2.com
等等。
英文:

I do not get how one can handle errors receiving from the net package. I need to know what kind of error occurred to do the next step. Trying to parse the error message string is probably not the right way...

response, err := data.httpClient.Get("https://" + domain)
if err != nil {				
	fmt.Println("[!] error: ", err)
    /* 
    *  I want something like this in pseudo code:
    *  if error == DnsLookupError {
    *      action1()
    *  } else if error == TlsCertificateError {
    *      action2()
    *  } else if error == Timeout {
    *      action3()
    *  } ...
    */
}

Error messages I receive for example:

Get "https://example1.com": remote error: tls: internal error
Get "https://example2.com": dial tcp: lookup example2.com
etc.

答案1

得分: 4

你可以检查错误是否与几种常见的错误类型兼容。我是这样做的:

func classifyNetworkError(err error) string {
    cause := err
    for {
        // Unwrap was added in Go 1.13.
        // See https://github.com/golang/go/issues/36781
        if unwrap, ok := cause.(interface{ Unwrap() error }); ok {
            cause = unwrap.Unwrap()
            continue
        }
        break
    }

    // DNSError.IsNotFound was added in Go 1.13.
    // See https://github.com/golang/go/issues/28635
    if cause, ok := cause.(*net.DNSError); ok && cause.Err == "no such host" {
        return "name not found"
    }

    if cause, ok := cause.(syscall.Errno); ok {
        if cause == 10061 || cause == syscall.ECONNREFUSED {
            return "connection refused"
        }
    }

    if cause, ok := cause.(net.Error); ok && cause.Timeout() {
        return "timeout"
    }

    return sprintf("unknown network error: %s", err)
}
英文:

You can check whether the error is compatible with a few well-known error types. I did it like this:

func classifyNetworkError(err error) string {
	cause := err
	for {
		// Unwrap was added in Go 1.13.
		// See https://github.com/golang/go/issues/36781
		if unwrap, ok := cause.(interface{ Unwrap() error }); ok {
			cause = unwrap.Unwrap()
			continue
		}
		break
	}

	// DNSError.IsNotFound was added in Go 1.13.
	// See https://github.com/golang/go/issues/28635
	if cause, ok := cause.(*net.DNSError); ok && cause.Err == "no such host" {
		return "name not found"
	}

	if cause, ok := cause.(syscall.Errno); ok {
		if cause == 10061 || cause == syscall.ECONNREFUSED {
			return "connection refused"
		}
	}

	if cause, ok := cause.(net.Error); ok && cause.Timeout() {
		return "timeout"
	}

	return sprintf("unknown network error: %s", err)
}

huangapple
  • 本文由 发表于 2021年5月22日 14:48:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/67646842.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定