猿问

处理网络数据包读取超时后的错误

我使用的conn.SetReadDeadline是设置读取超时的方法conn,当conn.Read等待超过指定的时间就会返回并返回一个类型的错误*net.OpError。net在包装所有非错误后,此错误由包返回io.EOF。


我可以在用Unwrap(). 超时错误是 类型的错误*poll.DeadlineExceededError。我在我的代码中使用这样的语句来精确处理超时错误。


import "internal/poll"


_, err = conn.Read(p)


    if err != nil {

        if pe, ok := err.(*net.OpError); ok {

            err = pe.Unwrap()

            if timeout, ok := err.(*poll.DeadlineExceededError); ok {

                log.Error(fmt.Sprintf("%T, %s", timeout, timeout))

            }

        }

        return

    }

我在运行程序时收到use of internal package internal/poll not allowed错误消息。编译器告诉我不能使用内部包。


我用谷歌搜索并找到了删除internal文件夹的解决方案,这是最终解决方案吗?会有更好的解决方案吗?


慕森卡
浏览 229回答 1
1回答

叮当猫咪

该os包将该错误导出为os.ErrDeadlineExceeded(检查源代码)。你可以试试 :if errors.Is(err, os.ErrDeadlineExceeded) {    log.Error("Timeout error")}[编辑]实际上,在阅读@Brit 的评论后,这是检查该错误的记录方式。请参阅文档Conn.SetDeadline():如果超过截止日期,对 Read 或 Write 或其他 I/O 方法的调用将返回一个包含 os.ErrDeadlineExceeded 的错误。这可以使用 errors.Is(err, os.ErrDeadlineExceeded) 进行测试。错误是“超时”错误的另一个迹象是它是否有一个Timeout() bool方法,该方法true在调用时返回。这是net.Error接口的一部分(虽然这个接口有一个额外的方法,它被记录为已弃用),并由net.OpError类型(以及内部poll.DeadlineExceededError类型)实现。有几个函数(例如net.OpError.IsTimeout(),os.SyscallError.IsTimeout()公共函数os.IsTimeout())通过直接将错误值转换为timeout接口来实现超时检查。如果你想处理可以被包装成另一个的错误,你可能想要isTimeout()使用以下方法实现你自己的检查errors.As(...):// isTimeout : use errors.As() to unwrap errors and check if a sub error is a Timeout errorfunc isTimeout(err error) bool {    var terr interface{ Timeout() bool }    return errors.As(err, &terr) && terr.Timeout()}https://go.dev/play/p/OhhKY3XsGjZ注意 :isTimeout()上面的函数和调用之间的区别在于errors.Is(err, os.ErrDeadlineExceeded)后者将尝试完全匹配一个ErrDeadlineExceeded(这主要是通过设置SetDeadline()一些类似文件或连接的对象来触发的),而后者可能会为尝试匹配的错误返回 true出于其他原因宣传“我是超时错误”(例如:HTTP“408 请求超时”响应)注:以上所有链接均参考go 1.18.3。根据您使用的 go 版本,您可能需要调整上面的一些代码(例如:os.ErrDeadlineExceeded在go1.15中添加的)
随时随地看视频慕课网APP

相关分类

Go
我要回答