在golang中捕获“绑定:已使用的地址”

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在golang中捕获“绑定:已使用的地址”相关的知识,希望对你有一定的参考价值。

我想在golang中捕获“bind:address has in use”错误。

conn, err := net.ListenUDP("udp", addr)
if err != nil {
    if CATCH_BIND_ERROR(err) {
         // Do something if 'addr' is already in use
    } else {
         panic(err)
    }
}

有没有办法实现CATCH_BIND_ERROR功能?

答案

简单的方法是检查错误的文本:

conn, err := net.ListenUDP("udp", addr)
if err != nil && err.Error() == "bind: address already in use" {
    // Failed to bind, do something
}
if err != nil {
    // Some other error
    panic(err)
}

对于这样的简单情况,这可能就足够了。然而,这种方法有点脆弱:

  1. 如果库曾经更改错误消息(这确实会不时发生,虽然在这个特定实例中可能不太可能),但检查会中断
  2. 如果你这样做检查一些包装函数,也可能返回其他类型的错误,你可能,至少在理论上,如果某些其他功能返回具有相同文本的错误,则可能会收到误报(在这种情况下也可能不太可能) )

为了缓解这些问题,您可以检查特定的错误类型,而不仅仅是文本表示。在您的示例中,net包提供了一些自定义错误。 ListenUDP方法返回net.OpError,这意味着您可以更仔细地检查它。例如:

conn, err := net.ListenUDP("udp", addr)
if opErr, ok := err.(*net.OpError); ok {
    if opErr.Op == "listen" && strings.Contains(opErr.Error.Error(), "address already in use") {
        // Failed to bind, do something
    }
}
if err != nil {
    // Some other error, panic
    panic(err)
}

在这种情况下,我们仍然依赖于文本检查,因此未来库更改仍有可能破坏测试。但是通过检查net.OpError类型,我们确实减轻了第二个风险,可能会引发一些具有相同文本的其他错误。

另一答案

在Windows上,错误消息是“Only one usage of each socket address (protocol/network address/port) is normally permitted.

此外,在本地化的情况下,消息将改变。

以下是捕获“已使用地址”错误的可能解决方案:

func isErrorAddressAlreadyInUse(err error) bool {
    errOpError, ok := err.(*net.OpError)
    if !ok {
        return false
    }
    errSyscallError, ok := errOpError.Err.(*os.SyscallError)
    if !ok {
        return false
    }
    errErrno, ok := errSyscallError.Err.(syscall.Errno)
    if !ok {
        return false
    }
    if errErrno == syscall.EADDRINUSE {
        return true
    }
    const WSAEADDRINUSE = 10048
    if runtime.GOOS == "windows" && errErrno == WSAEADDRINUSE {
        return true
    }
    return false
}

要使用此功能:

conn, err := net.ListenUDP("udp", addr)
if err != nil {
    if isErrorAddressAlreadyInUse(err) {
        // Do something if 'addr' is already in use
    } else {
        panic(err)
    }
}

以上是关于在golang中捕获“绑定:已使用的地址”的主要内容,如果未能解决你的问题,请参考以下文章

golang goroutine例子[golang并发代码片段]

如何在片段中从相机捕获图像,

从片段中捕获图像

代码片段 - Golang 实现简单的 Web 服务器

代码片段 - Golang 实现集合操作

golang panic的捕获