0

0

为了胜利早早退出!

心靈之曲

心靈之曲

发布时间:2024-12-14 11:09:24

|

462人浏览过

|

来源于dev.to

转载

为了胜利早早退出!

超简短摘要:当出现错误时退出程序可能是个好主意。使用 gobail 会让您的生活更轻松。

当你的 go 代码出现错误时,你通常会看到类似这样的内容:

err := myfunc()
if err != nil {
    return fmt.errorf("doing my thing: %w", err)
}

您会在这个示例中注意到一些事情:

  1. 您必须检查是否有错误
  2. 有一些文本可以帮助诊断错误
  3. 错误被包装,与文本一起传回

那么接下来会发生什么?好吧,这一切又发生了。您检查错误值,描述它,然后将其传回。然后一切又重新开始。

我们为什么要这样做?为什么要这么努力?

这一切都取决于您正在编写的软件。当你遇到错误时,你必须做出决定。这个错误会发生什么?

如果您正在编写一个响应请求的 http api,那么最终您将获得某种 http 处理程序,并将该错误转换为某种响应 - 也许是一个带有礼貌提醒格式的小 400正确请求或可能返回 500 以及有关应用程序运行状况的令人担忧的消息。或者,如果您正在编写某种 cli 工具,那么您可能会决定错误最终会一直传递回您的主函数。对于任何类型的程序,您可能会认为已经足够了 - 该程序应该结束,因为您无法做任何其他事情。

让我们看看最后一个选项。什么时候退出程序合适?我能想到的几个原因:

a.没有别的办法了,错误太严重了,一切都必须立即停止
b.终止程序没有任何后果(不需要清理,没有状态可以响应)
c.尽早停止是可取的,也许你有一个监视器可以干净地重新启动该过程

无论什么原因,你都需要考虑如何干净利落地退出。现在您可能尝试的第一件事是:

err := myfunc()
if err != nil {
    fmt.printf("doing my thing: %v", err)
    os.exit(1)
}

它看起来与我们原来的错误处理代码非常相似,但有一些重要的区别。第一个是显而易见的——那里有一个很棒的stop-right-g*****n-now声明。你的程序不会继续下去。第二点也许更重要。调用此示例的代码不必担心处理任何错误。没有需要测试的其他代码路径 - 我们可以相信调用代码没有要测试的 if 块,因为没有返回任何需要我们检查的内容。

测试你的出口

所以,当我建议你应该相信你的退出代码会起作用时,我可能有点热情。您可能应该检查新程序停止的原因是否正确。

尝试 1 - 运行你的程序

这感觉应该很容易。这里有一些需要考虑的事情 - 在最简单的情况下,您只需运行程序并触发错误条件。例如,让 cli 工具打开一个不存在的文件。对于一些简单的情况,您可以手动执行此操作。当测试数量增加时,您可能需要某种自动化来帮助您。

快速旁注 - 这可能是另一篇博客文章的主题,但我目前最喜欢的测试 cli 工具的方法是使用 godog 来编写测试。它可能有点复杂,但我发现它非常强大。以下是我如何使用layli和wait-for来处理它的一些很好的例子。

这种方法会让您走得很远,但有时可能很难创造条件来正确执行您想要确信的所有代码路径。

尝试 2 - 模拟出口

好的,现在我们将使用 go 语言的一些功能。我们实际上不必调用 os.exit - 我们可以调用看起来像它的东西。所以看看这个:

DeepL Write
DeepL Write

DeepL推出的AI驱动的写作助手,在几秒钟内完善你的写作

下载
type exitfunc func(code int)

var customexit exitfunc = os.exit

func myfunc() {
    err := someotherfunc()
    if err != nil {
        fmt.printf("doing my thing: %v", err)
        customexit(1)
    }
}

那么我们如何利用这一点进行测试呢?由于函数现在已转换为变量 (customexit),因此我们可以用我们想要执行的其他操作替换该值。就像这样...

package sameastheabovecode

func testomgitsallgonewrong(t *testing.t) {
    oldexit := customexit
    defer func() {
        // make sure we reset the exit so it can be used elsewhere
        customexit = oldexit
    }

    exitcalled := false
    exitcode := 0
    customexit = func(code int) {
        exitcalled = true
        exitcode = code
    }

    // set up the mocks so that someotherfunc returns an error

    myfunc()

    // assume that we're using the fantastic stretchr/testify library here
    assert.true(t, exitcalled)
    assert.equal(t, 1, exitcode)
}

这是一种对单元测试更加友好的方法。您可以检查使用的退出代码是否正确 - 并且您实际上调用了退出函数。

从表面上看,这看起来不错,但有一个大问题 - 如果您的测试通过,那么您的程序将继续并在您期望函数退出时执行该函数的其余部分。即使测试设置意味着其余的执行无效并导致测试出现问题(例如引起恐慌),它仍将继续。

删除代码以删除测试

嗯,这听起来有点极端!

我觉得我应该解释一下......通常在“管理良好”的公司中,您需要确保每一行代码都已被证明是有效的,然后才能放在客户面前。使用上述技术,您可能无法生成正确的覆盖率指标来证明您的能力良好。即使推理起来微不足道。
上面的所有示例都假设当我们收到错误时,我们必须检查它以决定做什么(报复性退出)。如果我们能够退出而无需检查是否存在错误,那不是很好吗?

让我们看看我们能做什么。

func checkexit(err error) {
   fmt.printf("doing my thing: %v", err)
   customexit(1)
}

func myfunc() {
    checkexit(someotherfunc())
}

看一下上面的例子。功能是相同的,但 myfunc 的实现现在更加简单 - 没有条件。我们可以在自己的测试中检查 checkexit 函数的实现,这意味着 myfunc() 中的任何新内容都可以更容易地验证。

戈贝尔介绍

创建了一个新的库 gobail,它可以让您确信如果出现错误,它将得到处理,而无需增加您自己的代码的复杂性。看起来像这样:

func myfunc() {
    gobail.run(someotherfunc()).orexit("with message")
    gobail.run(yetanotherfunc()).orexit("with message")
}

这个库已经过全面测试,并具有覆盖率指标,以证明这一点。您可以安全地使用它,而不必担心错误会被跳过。它还将处理具有 2 个返回值的函数,如下所示:

gobail.Return2(return2ValsAndError()).OrExitMsg("something went wrong: %v")

另请注意,您包含了导致所有问题的错误。

也可以发生恐慌而不是退出,在调用恐慌时打印堆栈跟踪和程序中的其他上下文信息。请查看文档以了解更多详细信息。

隔离依赖关系

当您使用 gobail 编写软件时,您会注意到在与外部库交互时大多数情况下都必须使用它。这具有您通常需要编写来处理所有错误情况的附加代码,可以将其包装在对 return 或 return2 的调用中,并假设我们将在必要时退出。

结论

有时需要退出程序而不是详细处理错误。 gobail 库已创建并经过验证,因此您不必担心证明这一点的细节。

如果您发现可以进行的改进或只是有建议,请在存储库上提出 pr 或问题,开发人员会尽快处理!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

773

2023.08.22

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

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

395

2023.07.18

堆和栈区别
堆和栈区别

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

575

2023.08.10

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

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

395

2023.07.18

堆和栈区别
堆和栈区别

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

575

2023.08.10

http500解决方法
http500解决方法

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

403

2023.11.09

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

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

418

2023.11.14

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

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

2173

2024.03.12

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

31

2026.01.26

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 3万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.5万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号