首页 后端开发 Golang 为了胜利早早退出!

为了胜利早早退出!

Dec 25, 2024 pm 08:32 PM

Quitting early for the win!

超简短摘要:当出现错误时退出程序可能是个好主意。使用 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 - 我们可以调用看起来像它的东西。所以看看这个:

err := myFunc()
if err != nil {
    return fmt.Errorf("doing my thing: %w", err)
}
登录后复制
登录后复制
登录后复制

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

err := myFunc()
if err != nil {
    fmt.Printf("doing my thing: %v", err)
    os.Exit(1)
}
登录后复制
登录后复制
登录后复制

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

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

删除代码以删除测试

嗯,这听起来有点极端!

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

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

err := myFunc()
if err != nil {
    return fmt.Errorf("doing my thing: %w", err)
}
登录后复制
登录后复制
登录后复制

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

戈贝尔介绍

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

err := myFunc()
if err != nil {
    fmt.Printf("doing my thing: %v", err)
    os.Exit(1)
}
登录后复制
登录后复制
登录后复制

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

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)
    }
}
登录后复制

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

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

隔离依赖关系

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

结论

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

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

以上是为了胜利早早退出!的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1664
14
CakePHP 教程
1422
52
Laravel 教程
1316
25
PHP教程
1266
29
C# 教程
1239
24
Golang的目的:建立高效且可扩展的系统 Golang的目的:建立高效且可扩展的系统 Apr 09, 2025 pm 05:17 PM

Go语言在构建高效且可扩展的系统中表现出色,其优势包括:1.高性能:编译成机器码,运行速度快;2.并发编程:通过goroutines和channels简化多任务处理;3.简洁性:语法简洁,降低学习和维护成本;4.跨平台:支持跨平台编译,方便部署。

Golang vs. Python:性能和可伸缩性 Golang vs. Python:性能和可伸缩性 Apr 19, 2025 am 12:18 AM

Golang在性能和可扩展性方面优于Python。1)Golang的编译型特性和高效并发模型使其在高并发场景下表现出色。2)Python作为解释型语言,执行速度较慢,但通过工具如Cython可优化性能。

Golang和C:并发与原始速度 Golang和C:并发与原始速度 Apr 21, 2025 am 12:16 AM

Golang在并发性上优于C ,而C 在原始速度上优于Golang。1)Golang通过goroutine和channel实现高效并发,适合处理大量并发任务。2)C 通过编译器优化和标准库,提供接近硬件的高性能,适合需要极致优化的应用。

Golang的影响:速度,效率和简单性 Golang的影响:速度,效率和简单性 Apr 14, 2025 am 12:11 AM

GoimpactsdevelopmentPositationalityThroughSpeed,效率和模拟性。1)速度:gocompilesquicklyandrunseff,ifealforlargeprojects.2)效率:效率:ITScomprehenSevestAndArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdEcceSteral Depentencies,增强开发的简单性:3)SimpleflovelmentIcties:3)简单性。

Golang vs. Python:主要差异和相似之处 Golang vs. Python:主要差异和相似之处 Apr 17, 2025 am 12:15 AM

Golang和Python各有优势:Golang适合高性能和并发编程,Python适用于数据科学和Web开发。 Golang以其并发模型和高效性能着称,Python则以简洁语法和丰富库生态系统着称。

Golang和C:性能的权衡 Golang和C:性能的权衡 Apr 17, 2025 am 12:18 AM

Golang和C 在性能上的差异主要体现在内存管理、编译优化和运行时效率等方面。1)Golang的垃圾回收机制方便但可能影响性能,2)C 的手动内存管理和编译器优化在递归计算中表现更为高效。

Golang vs.C:性能和速度比较 Golang vs.C:性能和速度比较 Apr 21, 2025 am 12:13 AM

Golang适合快速开发和并发场景,C 适用于需要极致性能和低级控制的场景。1)Golang通过垃圾回收和并发机制提升性能,适合高并发Web服务开发。2)C 通过手动内存管理和编译器优化达到极致性能,适用于嵌入式系统开发。

表演竞赛:Golang vs.C 表演竞赛:Golang vs.C Apr 16, 2025 am 12:07 AM

Golang和C 在性能竞赛中的表现各有优势:1)Golang适合高并发和快速开发,2)C 提供更高性能和细粒度控制。选择应基于项目需求和团队技术栈。

See all articles