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

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操作系统中测试系统时,我发现了问题.

[EDIT]

我找到了一种使用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]

更新后,郑回答.

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函数中更简单的代码,可以考虑使用类型switch (http://golang.org/doc/effective_go.html#type_switch).

Go相关问答推荐

无法找到与golang、nginx和postquist进行的docker-compose./主要

如何创建两个连接的io.ReadWriteClosers以用于测试目的

gorm插入不支持的数据

AWS S3 SelectObjectContent在AWS SDK v2 for Go中不返回结果

仅呈现一个模板的GIN Web应用程序

如何在gofr发起的服务间调用请求中添加Authorization Header?

正确使用pgtype的方法

日志(log)文件不在 golang 的日志(log)目录中

Golang telegram 机器人

使用Cookie身份验证的Gorilla Golang Websocket优化

为什么 net/http 不遵守超过 30 秒的超时持续时间?

缺少签名帮助文档

在嵌套模板中使用变量,它也被定义为 go 模板中的变量?

如何确定作为函数参数传递的指针是否正在被修改或副本是否正在被修改?

在 Golang 中,如何将接口作为泛型类型与 nil 进行比较?

如何将多个切片打印为一个切片?

在 docker kill --signal=SIGX 上以这种方式关闭容器内运行的 go 应用程序是否安全?

使用 `didip/tollbooth` 限制每小时最大请求数

处理程序中的无限循环

如何访问Go 1.18泛型 struct (structs)中的共享字段