(go语言教程)(go语言教程全套)

(go语言教程)(go语言教程全套)

私信我回复“Go”免费领取资料

精心整理了《手撕GO语言》219页免费资料,私信我回复”Go”免费获取网盘链接和提取码。

Go语言是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言,它用批判吸收的眼光,融合C语言、Java等众家之长,将简洁、高效演绎得淋漓尽致。

很多技术爱好者喜欢 Go 语言有以下几个原因:

1. 语言本身极其简洁(只有 25 个关键字);

2.能轻而易举地实现交叉编译;

3.天然支持创建可靠的 HTTP 服务器;

从根本上来讲,Go 是一种 boring 的语言,可能这就是为什么可以用它来开发一些诸如 Docker 和 Kubernetes 等很棒的项目,像 Cloudflare 等具有高性能和弹性要求的公司也正在使用它。

尽管上手很容易,但是有很多细节还是值得关注。如果你在不清楚的情况下编写代码,很可能会导致各种稀奇古怪的问题,并且很难发现和纠正错误。

下面会给大家列举一些常见错误,是在 review 生产代码时发现的。希望你再遇到相同问题时能轻松地解决。

1.HTTP 超时时间

HTTP 超时时间,其实在点击已经跟大家讨论过这个问题。但仍然值得再提一提,因为好的解决方案总是需要更多的时间思考的。

使用默认的 HTTP 客户端可以发出 HTTP 请求,为了说明问题,下面是一个使用 GET 请求访问 google.com 的例子:

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

正如文章指出的,默认的 HTTP 客户端没有设置超时时间,这意味着请求有可能会被长时间挂起(ps:具体原因可以查看原文)

所以,解决这个问题最好的办法是什么呢?

&http.Client{Timeout: time.Minute},给 HTTP 客户端定义一个合理的超时时间。你也可以考虑给 HTTP 请求加上 context,这样做有几个好处:

  1. 有能力取消正在进行的 HTTP 请求;
  2. 为一些特殊请求指定超时时间;

第 2 个好处显得尤为重要,比如你知道有几个请求需要耗时很长时间,超过 1 个小时。但是你又不想每个请求都设置这么长的超时时间,你就可以只针对特殊请求设置比较长的超时时间。

上面的例子中,如果加上 context 代码会像下面这样:

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

请求时间如果超过了超时时间,c.Do() 调用就会返回 DeadlineExceeded 错误,可以很容易地处理错误或者重试。

2.数据库连接

我参与的每一个 Go 项目几乎都会出现数据库连接问题。我认为对刚入门 Go 语言的新手来说,有个难以绕过去的点,sql.DB 对象是并发安全的连接池,而不是单个数据库连接。这意味着连接使用完之后如果没有返还给进程池,会轻易导致连接数耗尽,甚至最后导致应用程序宕掉。

例如,数据库连接池包含打开和空闲连接,分别是通过下面这些选项设置的:

  • SetConnMaxLifetime,连接可以重用的最长时间;
  • SetMaxIdleConns,最大的空闲连接数量;
  • SetMaxOpenConns,最大的打开连接数量;

需要注意的是,即使你的最大打开连接数设置成 200,如果连接使用完不返还连接池,应用程序也有可能会耗尽数据库能接受的最大连接数,最后导致宕机、重启服务。你需要检查数据库设置,以确保正确设置了这些参数。

如果数据库没有设置这些参数,应用程序将轻而易举地耗尽数据库能接受的连接数。

让我们回到进程池的问题上,查询数据库之后,很多开发人员会忘记关闭 *sql.Rows 对象,这就会导致超出最大连接数限制,并导致死锁或者高延迟。下面给大家展示下类似的代码片段:

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

相信你也注意到,正如能在 HTTP 请求上添加 context 一样,我们也可以在数据库查询时添加超时时间的 context。这没什么问题。

正如上面讨论的,我们需要关闭 rows 对象将连接返还给进程池,防止连接数超出。

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

如果在函数或者包之间传递数据库连接,尤其难以发现这一点。

3.goroutine 或者内存泄漏

最后一个要讨论的常见问题是 goroutine 泄漏,一般这个问题难以发现,但通常是由开发人员的错误引起的。

使用 channel 时通常会发生这种问题,比如:

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

如果我们不关闭通道 c 或者 someFunc() 不返回错误,我们初始化的 goroutine 将会挂起直到程序终止。

我们不可能找出每一个导致 goroutine 泄漏的 地方,我通常采用两种方法来检测和消除它们。

第一种方法是在单元测试方法里使用探测器,比如使用 Uber 开源的 goleak 库,就像下面这个例子一样:

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

这段代码就会验证,在代码优美关闭 30s 之后是否还有多余的 goroutine 在运行。

另一种方法是在应用程序的运行实例上使用 Go profiler,并查看存活的 goroutine 数量。其中一种方法就是使用 net/http/pprof 库,并查看生成的火焰图。

就像下面这样使用它:

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

上面这段代码,pprof 占用 6060 端口,对于特别严重的泄漏,如果你刷新将会看到协程数量在增多;对于更多的一些微小泄漏问题,则需要查看 profile 发现具体的问题,profile 页面就像下面这样:

(go语言教程)(go语言教程全套)

私信我回复“Go”免费获取资料

如果你的应用程序是空闲的,但是你又看见大数据量的 goroutine,这说明程序已经有问题了。确认泄漏位置之后,我仍然建议在单元测试中使用探测器,以确保解决问题。

总结

希望上面讨论的这些常见错误,如果以后你也遇到,可以帮助你更快地识别并完美地解决问题。

声明:我要去上班所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,版权归原作者马哥教育IT实战所有,原文出处。若您的权利被侵害,请联系删除。

本文标题:(go语言教程)(go语言教程全套)
本文链接:https://www.51qsb.cn/article/m8xor.html

(0)
打赏微信扫一扫微信扫一扫QQ扫一扫QQ扫一扫
上一篇2023-02-22
下一篇2023-02-22

你可能还想知道

发表回复

登录后才能评论