当前位置:首页 > 科技  > 软件

从错误中学习:了解 Go 编程的六个坏习惯

来源: 责编: 时间:2024-01-08 09:16:12 127观看
导读使用Go和使用其他编程语言中一样,需要了解常见错误和不良实践,才能编写既干净又高效的代码。本文讨论的一些实践并不一定都是不好的,在特定情况下很有用。 然而,我们需要知道可能会有什么问题,为什么应该回避某些习惯,以及

使用Go和使用其他编程语言中一样,需要了解常见错误和不良实践,才能编写既干净又高效的代码。qbu28资讯网——每日最新资讯28at.com

本文讨论的一些实践并不一定都是不好的,在特定情况下很有用。 然而,我们需要知道可能会有什么问题,为什么应该回避某些习惯,以及如何避开常见的陷阱。qbu28资讯网——每日最新资讯28at.com

qbu28资讯网——每日最新资讯28at.com

1. 使用init()

Go中的init()函数是一个特殊函数,在main函数之前执行。qbu28资讯网——每日最新资讯28at.com

"如果初始化对于任何包都很重要,为什么init()在Go中被认为是一个不好的做法?"qbu28资讯网——每日最新资讯28at.com

qbu28资讯网——每日最新资讯28at.com

是的,虽然init()函数确实有助于在运行核心逻辑之前进行初始化,但其执行顺序可能很难理解,可能导致对初始化顺序的混淆。qbu28资讯网——每日最新资讯28at.com

// package Afunc init() {}// package B func init() {}// which run first?

想象一下,有两个模块在安装时相互依赖,但位于不同的包中。结果我们最终需要编写更复杂的代码来管理时序,更糟的是,甚至可能陷入死锁情况。qbu28资讯网——每日最新资讯28at.com

使用init()的另一个缺点是测试会变得复杂。因为这些函数是自动运行的,无法选择何时执行。qbu28资讯网——每日最新资讯28at.com

缺乏控制使得设置测试用例成为一项挑战。qbu28资讯网——每日最新资讯28at.com

我曾经遇到过一个问题,我的服务在部署后花了很长时间才准备好。我在main()函数的开始处设置了一个断点,但从未触发。qbu28资讯网——每日最新资讯28at.com

qbu28资讯网——每日最新资讯28at.com


qbu28资讯网——每日最新资讯28at.com

经过冗长的调试后,我们发现一个成员使用了某个包中的init()函数从一个大文件加载一个大数据集,这让我们花费大量时间去解决这么一个小问题。qbu28资讯网——每日最新资讯28at.com

2. 使用全局变量

Go中的全局变量可能会带来类似单例的问题,特别是当这些全局变量很复杂时(比如映射、切片或指针)。qbu28资讯网——每日最新资讯28at.com

"那么,全局变量有什么大不了的?"qbu28资讯网——每日最新资讯28at.com

qbu28资讯网——每日最新资讯28at.com

  • 竞争条件: 当有多个程序试图同时访问同一个全局变量时,事情可能会变得混乱。
  • 更少的可测试性: 应用程序依赖于全局变量,意味着有状态,从而在单元或集成测试期间,这些全局变量需要与main()函数中的内容或在生产环境中部署的内容保持一致。
  • 模块化程度较低,可重用性较差: 可以从任何地方访问全局变量,很难跟踪其使用方式和位置。

因此,这里的建议是保持对包的封装。qbu28资讯网——每日最新资讯28at.com

从而使得代码更容易移动,并且不太可能破坏其他东西。通过避免使用全局变量,可以使代码不那么受约束,并且更容易更新或复用。qbu28资讯网——每日最新资讯28at.com

3. 忽略错误信息

用Go编程时,错误是不可避免的,知道如何处理错误可以让我们避免各种各样的问题。qbu28资讯网——每日最新资讯28at.com

"忽略错误真的那么糟糕吗?"qbu28资讯网——每日最新资讯28at.com

qbu28资讯网——每日最新资讯28at.com

是的,完全正确。qbu28资讯网——每日最新资讯28at.com

一些Go新手可能会用"_"符号将错误撇在一边,但忽略函数返回的错误值,可能会带来麻烦。qbu28资讯网——每日最新资讯28at.com

如果不对错误进行管理,也许程序会出现panic和crash。qbu28资讯网——每日最新资讯28at.com

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

跳过错误可能会适得其反,尤其是对于线上生产环境,调试会成为一场噩梦。总是--我的意思是总是--检查错误并采取正确的措施以保持代码顺利运行。qbu28资讯网——每日最新资讯28at.com

4. 避免GOTO

无论用Go还是其他语言,避免使用"goto"是大家的共识。qbu28资讯网——每日最新资讯28at.com

使用goto会破坏代码的自然流程。qbu28资讯网——每日最新资讯28at.com

会破坏我们理解不同代码段之间关系的方式,让我们很难在不弄得乱七八糟的情况下修改代码。qbu28资讯网——每日最新资讯28at.com

此外,调试也变得更加令人困惑,测试也更加棘手。qbu28资讯网——每日最新资讯28at.com

从本质上讲,依赖goto往往会产生更多错误,并难以深入了解问题。因此,作为最佳实践,明智的做法是避开它。qbu28资讯网——每日最新资讯28at.com

5. 跳过Defer和Recover

如果你忽略"defer"和"recover",就失去了对panic的坚实保护。qbu28资讯网——每日最新资讯28at.com

为什么?qbu28资讯网——每日最新资讯28at.com

因为当出现panic时,"defer"仍然会起作用,而"recover"会抓住panic,让我们有机会处理不可预见的问题[2]。qbu28资讯网——每日最新资讯28at.com

看看这个例子,其中'file.Close()'只是放在末尾,这不是一个Go风格的解决方案:qbu28资讯网——每日最新资讯28at.com

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

相反,像这样使用"defer":qbu28资讯网——每日最新资讯28at.com

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

在打开文件后立即调用defer file.Close()可以确保即使readFile()遇到panic,文件也会被关闭。此外,还可以方便的提醒我们在打开资源后立即进行清理。qbu28资讯网——每日最新资讯28at.com

6. 过多使用context.Background()

Go的context功能非常有用,当代码与数据库或网站对话时,有助于管理时间限制等事情。qbu28资讯网——每日最新资讯28at.com

如果没有设定截止时间,应用可能会陷入阻塞,被数以百万计的请求淹没。qbu28资讯网——每日最新资讯28at.com

通过一个特殊功能,可以很容易的设置时间限制。qbu28资讯网——每日最新资讯28at.com

该函数有三种时间选择: Fast(0.5秒)、Medium(3秒)和Slow(10秒)。这样就不用一直使用context.Background(),而且可以为每个任务选择合适的时间限制。qbu28资讯网——每日最新资讯28at.com

以下是Fast的一些示例代码:qbu28资讯网——每日最新资讯28at.com

const FastTimeout = 500 * time.Millisecondfunc WrapCustomContext(ctx context.Context, dur time.Duration) (context.Context, context.CancelFunc) {  return context.WithTimeout(ctx, 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)}

有了这些函数,就可以选择正确的时间限制,应用也因此运行得更好。qbu28资讯网——每日最新资讯28at.com

好还是不好,只是一些概念,我们可以决定其真正含义。qbu28资讯网——每日最新资讯28at.com

所以,明智的使用"不好"的特性,它就能变成"最好"的方案。qbu28资讯网——每日最新资讯28at.com

参考资料:qbu28资讯网——每日最新资讯28at.com

  • [1]5+ BAD Practices In Go: Learn From Mistakes: https://levelup.gitconnected.com/5-bad-practices-in-go-learn-from-mistakes-13afb4d303b3
  • [2]What you know about defer in Go is not enough!: https://medium.com/@func25/what-you-know-about-defer-in-go-is-not-enough-2681d4b128c3

本文链接:http://www.28at.com/showinfo-26-57886-0.html从错误中学习:了解 Go 编程的六个坏习惯

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C++控制台彩色时钟的实现

下一篇: 什么是Helm?它是如何提升云原生应用私有化部署效率的

标签:
  • 热门焦点
  • 一加Ace2 Pro官宣:普及16G内存 引领24G

    一加Ace2 Pro官宣:普及16G内存 引领24G

    一加官方今天继续为本月发布的新机一加Ace2 Pro带来预热,公布了内存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引领,还有呢?#一加Ace2Pro#,2023 年 8 月,敬请期待。”同时
  • vivo TWS Air开箱体验:真轻 臻好听

    vivo TWS Air开箱体验:真轻 臻好听

    在vivo S15系列新机的发布会上,vivo的最新款真无线蓝牙耳机vivo TWS Air也一同发布,本次就这款耳机新品给大家带来一个简单的分享。外包装盒上,vivo TWS Air保持了vivo自家产
  • SpringBoot中使用Cache提升接口性能详解

    SpringBoot中使用Cache提升接口性能详解

    环境:springboot2.3.12.RELEASE + JSR107 + Ehcache + JPASpring 框架从 3.1 开始,对 Spring 应用程序提供了透明式添加缓存的支持。和事务支持一样,抽象缓存允许一致地使用各
  • 企业采用CRM系统的11个好处

    企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    记者丨宁晓敏 见习生丨汗青出品丨鳌头财经(theSankei) 前不久,爱奇艺发布了一份亮眼的一季报,不仅营收和会员营收创造历史最佳表现,其运营利润也连续6个月实现增长。自去年年初
  • 本地生活这块肥肉,拼多多也想吃一口

    本地生活这块肥肉,拼多多也想吃一口

    出品/壹览商业 作者/李彦编辑/木鱼拼多多也看上本地生活这块蛋糕了。近期,拼多多在App首页&ldquo;充值中心&rdquo;入口上线了本机生活界面。壹览商业发现,该界面目前主要
  • 冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    来源:直播观察提起&ldquo;冯提莫&rdquo;这个名字,很多网友或许听过,但应该不记得她是哪位主播了。其实,作为曾经的&ldquo;斗鱼一姐&rdquo;,冯提莫在游戏直播的年代影响力不输于现
  • 荣耀Magicbook V 14 2021曙光蓝版本正式开售,拥有触摸屏

    荣耀Magicbook V 14 2021曙光蓝版本正式开售,拥有触摸屏

    荣耀 Magicbook V 14 2021 曙光蓝版本正式开售,搭载 i7-11390H 处理器与 MX450 显卡,配备 16GB 内存与 512GB SSD,重 1.48kg,厚 14.5mm,具有 1.5mm 键盘键程、
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top