我正在学习go,并试图理解如何从通用错误类型中获取更详细的错误信息.我将使用的示例来自net软件包,特别是DialTimeout function.

签名是

func DialTimeout(network, address string, timeout time.Duration) (Conn, error)

error类型仅定义Error() string函数.如果我想找出DialTimeout失败的确切原因,我如何才能获得该信息?我发现可以使用类型断言来获取net.Error特定错误:

con, err := net.DialTimeout("tcp", net.JoinHostPort(address, "22"),
    time.Duration(5) * time.Second)
if err != nil {
    netErr, ok := err.(net.Error)
    if ok && netErr.Timeout() {
        // ...
    } 
} 

但那只能告诉我我是否超时了.例如,假设我想区分拒绝的连接和没有到主机的路由.我怎么才能做到这一点呢?

也许DialTimeout级别太高,不能给我提供这样的细节,但即使查看syscall.Connect个,我也不知道如何获得具体的错误.它只是说它返回泛型错误类型.将其与POSIXconnect进行比较,它会让我知道它失败的原因,并显示各种返回代码.

我的一般问题是:如果Golang文档不告诉我可能返回哪种类型的错误,我如何从通用的error类型中提取错误详细信息?

推荐答案

大多数网络操作返回一个*OpError,其中包含有关错误的详细信息

但对于您的情况,您希望将返回的错误断言为*net.OpError*net.OpError

if err != nil {
    if oerr, ok := err.(*OpError); ok {
        // Do something with oerr.Err
    }
}

一旦您这样做了,您就像Linux下的syscall一样进入了依赖平台的境地 可能会以不同于Windows下的方式失败.对于Linux,您将执行如下操作:

if oerr.Err == syscall.ECONNREFUSED {
    // Connection was refused :(
}

syscall软件包包含平台的重要错误常量.不幸地

找出类型

下一次当你想知道某个函数实际返回了什么,而你无法

 fmt.Printf("%#v\n", err)
 // &net.OpError{Op:"dial", Net:"tcp", Addr:(*net.TCPAddr)(0xc20006d390), Err:0x6f}

它将打印详细的类型信息,通常非常有用.

Go相关问答推荐

语法-for循环中的initit陈述是否允许分配?

如何在定制普罗米修斯出口商中测试动态计量注册?

如何修复Go中调用GetRawInputDeviceInfA Windows API函数时的错误?

困扰围棋官方巡回赛的S建议所有方法都使用同一类型的接收器

允许在 struct 中使用复合作为函数参数

由docker中的nginx提供的样式和图像在页面上不起作用

无法在32位计算机上运行Golang应用程序

无法读取postman 中的表单数据

由于 main.go 文件中的本地包导入导致构建 docker 容器时出错

你如何在 Golang 代码中测试 filepath.Abs​​ 失败?

如何使用 go 包设置标头键和值:shurcooL/graphql 或 hasura/go-graphql-client?

使用图像解码 JPEG 时 colored颜色 不正确.解码并写入 PDF?

Go http.FileServer 给出意外的 404 错误

无法访问 Go 模块导入的远程存储库

如何在 GORM 中获取字段值

Go 加密库创建的 PKCS1 公钥与openssl rsa ...之间的区别

Golang API 的 HTTPS

不理解切片和指针

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

在 etcd 键值存储中禁用历史记录