从错误中学习改正Go语言六个坏习惯提高编程技巧

 更新时间:2024年01月16日 10:53:33   作者:Slagga  
这篇文章主要为大家介绍了从错误中学习改正Go语言五个坏习惯提高编程技巧示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

从他人的错误中学习,通过本指南避免常见陷阱和坏习惯,提高你的 Go 编程技巧

在 Go 语言中,就像在任何编程语言中一样,了解常见陷阱和坏习惯是编写干净、高效代码的关键。

尽管下面列出的某些做法通常被认为是不好的,但在某些情况下它们可以有效地使用。 这篇文章旨在提醒大家这些做法的问题所在,并教导如何避免这些陷阱。

让我们深入探讨。

1. 使用 init()

在 Go 中,init()函数是在主函数之前执行的特殊函数。

“如果在任何包中初始化是如此重要的过程,为什么在 Go 中init()被认为是一种不好的实践?” —— 读者

是的,虽然init()函数有助于在运行核心逻辑之前进行初始化,但它们的执行顺序可能难以理解。 这可能会导致关于初始化顺序的混乱。

如果两个模块互相依赖于初始化并位于不同的包中,则可能会增加复杂性并需要额外的代码添加等待逻辑。然而,这也可能导致死锁的可能性。

另一个init()函数的问题是它会使测试更加困难。因为它们自动运行,很难控制它们何时执行,这可能使设置测试用例和测试代码行为变得具有挑战性。

我遇到了一个问题,我的服务从部署状态到准备就绪需要 10 分钟的时间。我在主函数的第一行设置了断点,但它从未触发。

我们不得不调试所有的init()函数,发现一个队友在一个“我不记得的包”中使用了init()函数,从一个大文件加载了大量数据到内存中,这导致花费了很多时间追踪一个微小的问题。

2. 使用全局变量

这与使用单例模式时可能出现的问题类似,特别是当全局变量是复杂的,包含映射、切片或指针时。

  • 竞态条件(Race condition):当使用全局变量时,多个goroutine同时访问全局变量会导致意外行为。这在Go语言中是一个很大的问题。

  • 难以测试:使用全局变量会使你的项目更具状态,这意味着当你开始单元测试/集成测试时,全局变量必须与运行main()或生产环境时相同。

  • 不够模块化且难以重用:难以组织和封装数据,因为任何包或模块都可以访问它们。这可能会导致代码不够模块化,更难以理解,因为很难确定数据来自哪里以及如何使用它们。

通常建议封装您的包,使其可以在不影响其他包的情况下移动。使用全局变量可能会使您的代码更紧密耦合,更难以修改或重用。

3. 忽略错误消息

错误是Go编程的内在部分,处理它们以优雅的方式确保在发生错误时不会发生意外情况非常重要。

忽略错误消息的方法是使用“_”符号,这样做会丢弃函数返回的错误值,可能会导致意外行为。

检查错误并适当地处理它们以防止程序发生崩溃和崩溃非常重要。

// sample 1
func main() {
    var x interface{} = "hello"
    s := x.(int) // panic: interface conversion: interface {} is string, not int
    fmt.Println(s)
}
// sample 2
func main() {
    var x interface{} = "hello"
    s, _ := x.(int) // safe but DON'T
    fmt.Println(s)
}

忽略错误处理会导致生产代码中出现重大问题,因为这可能使得识别和修复错误变得困难。始终检查错误并适当地解决它们对于确保代码的顺畅运行非常重要。

4. GOTO语句 — 跳进陷阱

不仅在Go语言中,许多语言都认为使用“goto”语句是一种不良实践,因为它会使代码更难理解和维护。

原因是“goto”语句忽略了代码流程,使得在不引入错误的情况下难以理解代码的不同部分之间的依赖关系。

这可能会使得在运行时推理程序的状态变得困难,使得调试和测试变得更加困难。

使用“goto”可能会导致错误数量增加,使得更难以识别问题的根本原因。

5. 不使用Defer和Recover

利用“defer”和“recover”的主要原因是为了防止恐慌。“defer”甚至可以在发生恐慌时执行,而“recover”可以捕捉到恐慌,允许更加控制地处理意外情况。

这种使用方式被认为是不好的代码实践:

func readFile(filename string) {
    file, err := os.Open(filename)
    if err != nil {
        panic(err)
    }
    // Do something with the file
    file.Close() // <--- DONT
}

我们使用defer这种方式,这样即使readFile()函数出现panic,文件也会被关闭。此外,这样做也容易记住在open()函数之后立即放置关闭函数。

func readFile(filename string) {
    file, err := os.Open(filename)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    // Do something with the file
    ...
}

6. 使用太多次的context.Background()

在 Go 中,上下文是最强大的功能之一。当正确使用时,它可以作为提供程序、树流和流控制器。

在进行外部调用(例如数据库、HTTP 等)时,使用context.Background()context.ToDo()设置截止时间或超时非常重要。如果没有设置,当用户过多且外部服务没有及时响应时,可能会导致您的应用程序出现瓶颈。

我通常会编写一个上下文池的实用函数,其中包括 3 个函数来创建或包装具有超时的新上下文:快速(0.5 秒)、中等(3 秒)、慢速(10 秒)。这样,我就不必一直依赖context.Background(),并且可以轻松地为每个调用设置适当的超时时间。

const FastTimeout = 500 * time.Millisecond
func WrapCustomContext(ctx context.Context, dur time.Duration) (context.Context, context.CancelFunc) {
    return context.WithTimeout(context.Background(), dur)
}
func GenFastContext() (context.Context, context.CancelFunc) {
    return WrapCustomContext(context.Background(), FastTimeout)
}
func WrapFastContext(ctx context.Context) (context.Context, context.CancelFunc) {
    return WrapCustomContext(ctx, FastTimeout)
}

以上就是从错误中学习改正Go语言坏习惯提高编程技巧的详细内容,更多关于Go语言编程习惯的资料请关注脚本之家其它相关文章!

相关文章

  • 解决Golang中ResponseWriter的一个坑

    解决Golang中ResponseWriter的一个坑

    这篇文章主要介绍了解决Golang中ResponseWriter的一个坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang中对json的优雅处理方式

    Golang中对json的优雅处理方式

    这篇文章主要给大家介绍了关于Golang中对json的优雅处理方式,解析JSON在golang中很麻烦,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • Go语言常见错误之any没传递任何信息解决分析

    Go语言常见错误之any没传递任何信息解决分析

    Go语言,由于其高效强大的并行处理能力和优雅简单的设计哲学,一直以来都是编程世界的宠儿,然而,对于一些Go新手和甚至熟悉Go的程序员也可能会遇到一个常见的错误: any没传递任何信息,那么,如何规避这个错误,本文将揭示其中的秘密
    2024-01-01
  • golang替换无法显示的特殊字符(\u0000, \000, ^@)

    golang替换无法显示的特殊字符(\u0000, \000, ^@)

    这篇文章主要介绍了golang替换无法显示的特殊字符,包括的字符有\u0000, \000, ^@等,下文详细资料,需要的小伙伴可以参考一下
    2022-04-04
  • golang image图片处理示例

    golang image图片处理示例

    这篇文章主要介绍了golang image图片处理的方法,结合实例形式分析了Go语言针对图片的打开、读取、转换等相关操作技巧,需要的朋友可以参考下
    2016-07-07
  • win7下配置GO语言环境 + eclipse配置GO开发

    win7下配置GO语言环境 + eclipse配置GO开发

    这篇文章主要介绍了win7下配置GO语言环境 + eclipse配置GO开发,需要的朋友可以参考下
    2014-10-10
  • Golang 如何解析和生成json

    Golang 如何解析和生成json

    这篇文章主要介绍了Golang 如何解析和生成json,帮助大家更好的理解和学习golang,感兴趣的朋友可以了解下
    2020-09-09
  • go连接mysql的项目实践

    go连接mysql的项目实践

    本文主要介绍了go连接mysql的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Golang接口型函数使用小结

    Golang接口型函数使用小结

    接口函数指的是用函数实现接口,这样在调用的时候就会非常简便,这种方式适用于只有一个函数的接口,这里以迭代一个map为例,演示这一实现的技巧,对Golang接口型函数使用知识感兴趣的朋友一起看看吧
    2022-06-06
  • Go语言使用Json的方法实现

    Go语言使用Json的方法实现

    本文主要介绍了Go语言使用Json的方法实现
    2024-05-05

最新评论