讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在 Go 中正确使用递归实现带重试逻辑的 HTTP 请求

老墨大大_6512

老墨大大_6512

发布时间:2026-01-08 10:46:53

|

603人浏览过

|

来源于php中文网

原创

如何在 Go 中正确使用递归实现带重试逻辑的 HTTP 请求

本文详解 go 递归函数中“内层返回不等于外层终止”的常见误区,指出遗漏 `return` 导致外层代码继续执行、访问 nil `resp.body` 而引发 panic 的根本原因,并提供修复方案、健壮性增强建议及完整可运行示例。

在 Go 中,递归调用本身不会自动中断当前函数的后续执行——这是理解本问题的关键。当你写 registerDomain(domainName, n-1) 却未加 return 时,Go 会执行该递归调用,但调用返回后,外层函数仍会继续向下执行(即走到 ioutil.ReadAll(resp.Body) 这一行)。而此时若上一轮调用因 client.Do() 失败导致 errr != nil,则 resp 为 nil,resp.Body 也必然为 nil,进而触发 panic: invalid memory address or nil pointer dereference。

✅ 正确做法是:每次递归调用前必须显式 return,确保控制流立即返回,绝不继续执行后续可能依赖 resp 的语句。

以下是修复后的核心逻辑(已整合错误处理、资源清理与 nil 安全检查):

Json Schema Toolkit
Json Schema Toolkit

使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。

下载
func registerDomain(domainName string, maxRetries int) bool {
    if maxRetries <= 0 {
        return false
    }

    // 构造请求(此处省略具体实现)
    req, err := http.NewRequest("POST", "https://api.example.com/register", strings.NewReader(`{"domain":"`+domainName+`"}`))
    if err != nil {
        // 请求构造失败,立即重试(若允许)
        return registerDomain(domainName, maxRetries-1)
    }

    resp, err := client.Do(req)
    if err != nil {
        // HTTP 请求失败:resp 为 nil,不可访问 resp.Body
        if maxRetries == 1 {
            return false
        }
        return registerDomain(domainName, maxRetries-1) // ✅ 关键:return + 递归
    }
    defer func() {
        if resp != nil && resp.Body != nil {
            resp.Body.Close()
        }
    }()

    // 此时 err == nil ⇒ resp.Body 必然非 nil(Go 文档保证)
    bodyBytes, err := io.ReadAll(resp.Body)
    if err != nil {
        // 响应体读取失败(如网络中断、连接关闭)
        if maxRetries == 1 {
            return false
        }
        return registerDomain(domainName, maxRetries-1) // ✅ 同样需 return
    }

    // 解析响应逻辑(例如检查 HTTP 状态码、JSON 字段等)
    if resp.StatusCode != http.StatusOK {
        if maxRetries == 1 {
            return false
        }
        return registerDomain(domainName, maxRetries-1)
    }

    // 成功处理响应体...
    // 例如:json.Unmarshal(bodyBytes, &result)
    return true
}

? 关键注意事项:

  • 永远不要省略 return:递归调用后若不 return,外层函数将继续执行,极易引发 nil 指针解引用;
  • defer 需判空:resp 或 resp.Body 可能为 nil(尤其在 Do() 失败时),defer resp.Body.Close() 必须前置空值检查,否则 defer 本身也会 panic;
  • 避免无限递归:确保 maxRetries 严格递减且有明确下界(如 <= 0),防止栈溢出;
  • 考虑替代方案:对长时间运行任务(如题中 17 小时),建议改用循环重试 + 指数退避,更易控制超时、监控和中断,例如:
for i := 0; i < maxRetries; i++ {
    if success := tryRegister(domainName); success {
        return true
    }
    time.Sleep(time.Second * time.Duration(1<<uint(i))) // 指数退避
}
return false

总结:Go 的递归本质是普通函数调用,其返回值必须被显式 return 才能终止当前栈帧。将重试逻辑从“隐式递归跳转”改为“显式返回递归结果”,是避免 nil 访问 panic 的最直接、最可靠的修复方式。

热门AI工具

更多
讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

319

2026.04.23

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

5147

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2288

2023.08.10

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3163

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

834

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

6286

2024.03.12

http与https有哪些区别
http与https有哪些区别

http与https的区别:1、协议安全性;2、连接方式;3、证书管理;4、连接状态;5、端口号;6、资源消耗;7、兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

5330

2024.08.16

Go 语言 HTTP 编程与中间件开发教程合集
Go 语言 HTTP 编程与中间件开发教程合集

全面讲解 Go 语言 HTTP 编程的核心知识,涵盖 net/http 标准库的 Server/Handler/HandlerFunc 体系、DefaultServeMux 路由注册与自定义路由器、Request / ResponseWriter 请求响应处理、中间件(Middleware)链式设计模式与常见中间件(日志/CORS/认证/限流)开发、http.Client 的超时配置与连接池管理、Cookie / Session 处理、

441

2026.05.08

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

80

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 20.8万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 4.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn