Go网络错误处理需区分超时与连接失败:用net.Error.Timeout()和errors.Is(err, context.DeadlineExceeded)判超时;用errors.Is(err, syscall.ECONNREFUSED)等判底层错误;按类型差异化重试。
Go语言中处理网络连接错误,关键在于区分超时(timeout)和连接失败(connection refused / no route to host 等),并针对性地重试或终止。标准库的net和net/http包已内置对超时的支持,但需主动识别错误类型,不能仅靠err != nil做统一处理。
text.WithTimeout控制连接与读写超时推荐用context.Context统一管理超时,尤其适用于http.Client或自定义net.Dialer。它能同时覆盖“建立连接耗时过长”和“请求发出后响应迟迟不来”两种场景。
http.Client.Timeout仅作用于整个请求生命周期(含连接、写入、读取),不够精细;更推荐用http.Client.Transport配合context
&net.Dialer{Timeout: 5 * time.Second, KeepAlive: 30 * time.Second},再通过dialer.DialContext(ctx, "tcp", addr)实现可取消的连接ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second); defer cancel(),后续所有I/O操作传入该ctxGo中没有统一的“超时错误类型”,需检查错误是否实现了net.Error接口,并调用.Timeout()方法:
if netErr, ok := err.(net.Error); ok && netErr.Timeout() { /* 是超时 */ }context.DeadlineExceeded也属于超时,但它不是net.Error,需单独判断:errors.Is(err, context.DeadlineExceeded)
err.Error()含"timeout"字符串——不可靠,不同系统/驱动返回文案不一致连接阶段失败通常由net.Dial或http.Transport抛出,错误值多为*net.OpError,其Err字段嵌套具体系统错误:
errors.Is(err, syscall.ECONNREFUSED) → 对端明确拒绝(服务未启动)errors.Is(err, syscall.ENETUNREACH) 或 errors.Is(err, syscall.EHOSTUNREACH) → 网络不可达(防火墙、路由问题)errors.Is(err, dns.ErrNoAnswer) 或 strings.Contains(err.Error(), "no such host") → DNS解析失败(优先用net.DNSError类型断言)classifyNetworkError(err error) NetworkErrType函数,集中处理判断逻辑不是所有错误都适合重试。盲目重试可能加剧问题或掩盖真实故障: