Error handling Go错误处理、类型断言和net包

Error handling Go错误处理、类型断言和net包,error-handling,network-programming,go,Error Handling,Network Programming,Go,我正在学习go,并试图了解如何从泛型错误类型中获取更详细的错误信息。我将使用的示例来自net包,特别是 签名是 func拨号超时(网络、地址字符串、超时时间、持续时间)(连接、错误) 该类型仅定义Error()字符串函数。如果我想知道DialTimeout失败的确切原因,我该如何获得这些信息?我发现我可以使用类型断言来获取net.Error特定错误: con, err := net.DialTimeout("tcp", net.JoinHostPort(address, "22"), t

我正在学习go,并试图了解如何从泛型错误类型中获取更详细的错误信息。我将使用的示例来自net包,特别是

签名是

func拨号超时(网络、地址字符串、超时时间、持续时间)(连接、错误)

该类型仅定义
Error()字符串
函数。如果我想知道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的级别太高,无法提供这种详细信息,但即使查看,我也不知道如何获取具体错误。它只是说它返回一般错误类型。将其与Posix进行比较,Posix会让我知道它为什么会在各种返回代码中失败


我的一般问题是:如果golang文档没有告诉我可能返回什么类型的错误,我应该如何从通用
错误
类型中提取错误详细信息

大多数网络操作返回一个包含错误详细信息的 并实现了
net.Error
接口。所以对于大多数用例,使用
net.Error就足够了
就像你已经做的那样

但是对于您的情况,您希望将返回的错误断言为
*net.OpError
,并且 使用内部错误:

if err != nil {
    if oerr, ok := err.(*OpError); ok {
        // Do something with oerr.Err
    }
}
一旦您这样做,您就进入了Linux下作为系统调用的平台依赖领域 故障可能与Windows下的不同。对于Linux,您可以执行以下操作:

if oerr.Err == syscall.ECONNREFUSED {
    // Connection was refused :(
}
syscall
包包含平台的重要错误常量。不幸的是 golang网站仅显示syscall包。有关
ECONNREFUSED
,请参阅

找出类型 下一次,当您想知道某个函数实际返回了什么时,您无法 不管是正面还是反面,请尝试使用
fmt.Printf
中指定的
%#v
格式(和朋友):

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

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