error-handling - 检测不同类型网络错误的可移植方法

标签 error-handling network-programming go

我想确定网络级别发生了什么样的错误。我发现的唯一方法是使用正则表达式检查错误消息,但现在我发现这些消息可以使用不同的语言(取决于操作系统配置),因此很难被正则表达式检测到。有没有更好的方法?

package main

import (
  "github.com/miekg/dns"
  "net"
  "regexp"
)

func main() {
  var c dns.Client
  m := new(dns.Msg)

  m.SetQuestion("3com.br.", dns.TypeSOA)
  _, _, err := c.Exchange(m, "ns1.3com.com.:53")
  checkErr(err)

  m.SetQuestion("example.com.", dns.TypeSOA)
  _, _, err = c.Exchange(m, "idontexist.br.:53")
  checkErr(err)

  m.SetQuestion("acasadocartaocuritiba.blog.br.", dns.TypeSOA)
  _, _, err = c.Exchange(m, "ns7.storedns22.in.:53")
  checkErr(err)
}

func checkErr(err error) {
  if err == nil {
    println("Ok")
  } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
    println("Timeout")
  } else if match, _ := regexp.MatchString(".*lookup.*", err.Error()); match {
    println("Unknown host")
  } else if match, _ := regexp.MatchString(".*connection refused.*", err.Error()); match {
    println("Connection refused")
  } else {
    println("Other error")
  }
}

结果:

$ go run neterrors.go
Timeout
Unknown host
Connection refused

我在使用葡萄牙语作为默认语言的 Windows 操作系统中测试系统时发现了问题。

[编辑]

我找到了一种使用 OpError 的方法。这是使用新方法的 checkErr 函数。如果有人有更好的解决方案,我会很高兴知道!

func checkErr(err error) {
  if err == nil {
    println("Ok")
  } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
    println("Timeout")
  } else if opError, ok := err.(*net.OpError); ok {
    if opError.Op == "dial" {
      println("Unknown host")
    } else if opError.Op == "read" {
      println("Connection refused")
    }
  }
}

[EDIT2]

在seong回答后更新。

func checkErr(err error) {
  if err == nil {
    println("Ok")
    return

  } else if netError, ok := err.(net.Error); ok && netError.Timeout() {
    println("Timeout")
    return
  }

  switch t := err.(type) {
  case *net.OpError:
    if t.Op == "dial" {
      println("Unknown host")
    } else if t.Op == "read" {
      println("Connection refused")
    }

  case syscall.Errno:
    if t == syscall.ECONNREFUSED {
      println("Connection refused")
    }
  }
}

最佳答案

net 包与您的操作系统紧密配合。对于操作系统错误,Go std 库使用 pkg syscall。看看这里:http://golang.org/pkg/syscall/

net 包也可以返回 syscall.Errno 类型错误。

对于 checkErr 函数中的更简单代码,您可以考虑使用类型开关 (http://golang.org/doc/effective_go.html#type_switch)。

关于error-handling - 检测不同类型网络错误的可移植方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22761562/

相关文章:

go - 我可以在main中定义一个接收方法吗?

go - 如何在具有自定义传输的客户端上使用go-retryablehttp?

android - 如何验证 Google ID token ?

c# - 如何获取mac地址

network-programming - Apache ActiveMQ 与原始套接字的性能开销是多少?

node.js - babel-preset-es2015 错误安装

Python urllib2 无法在备用端口(不是 80)上打开本地主机?错误 10013

c - accept() 返回无效参数

vue.js - Vue JS如何全局捕获错误并将其显示在顶级组件中

symfony - 通过覆盖ExceptionController的Symfony自定义错误页面