1、 【致命】不是所有Panic都能捕获

我们知道Golang给开发人员提供recover()机制,对堆栈异常(panic)进行捕获并自定义其处理逻辑。下面举个例子:

构造一个除0的异常场景:

输出结果:

我们看到程序正常退出,没有异常,说明recover()按照预期捕获到panic异常;但不是所有panic都能通过recover()捕捉到的,比如:并发操作map实例。

构造并发操作map的场景:

输出结果:

以上结果可知,我们不能单纯依靠recover()解决函数内部所有panic异常,应该做到以下几点:

a) 通过编写代码校验,防止能预期到的panic,比如:空指针引用的指针判断。

b) 对于无法预期的panic,使用recover()捕获并加以处理。

c) 使用map时,必须要考虑是否存在并发读写场景,存在时,应使用ConcurrentMap组件或自己加sync.RWMutex进行加锁保护。

相关参考:

关于并发读写map导致的panic无法使用recover()捕获,是Go1.6增加的一个特性,https://golang.org/doc/go1.6#runtime;

当然这个并非是唯一一个无法通过recover()捕获的场景,还有可能Go本身的bug,https://github.com/golang/go/issues/21717;这个Bug在Go1.9.2才修复

2、 【严重】小心Map的内存泄露

大部分Golang程序做业务缓存实现时,都使用了map,看以下代码片段,简单模拟了这种使用场景:

增加环境变量GODEBUG=gctrace=1,运行可见,即使代码逻辑清空了map,但进程内存使用并没有像预期那样“实报实销”:

应如何解决:定期替换成新的map,释放旧的map对象。

3、 【提示】不是每次Map遍历都能得到相同排序的集合

经常遇到一些业务场景,需要将map的所有元素打印输出,在Golang里面实现是非常简单的,一个for range就可以实现,但结果却有点出人意料:

输出结果:

两次遍历的结果均不相同,这是为什么呢?这是Golang故意增加的一个随机数导致的,https://blog.golang.org/go-maps-in-action;所以如果对结果一致性有要求的业务逻辑,就不能简单的遍历map了,可以这样实现:

4、 【严重】客户端执行Response.Body.Close()后HTTP连接真的关闭了吗?

按照官方文档对标准库中的http client包的说明,在使用时需要主动调用Response.Body.Close()将连接关闭,但并不说明只要写了这句话就能关闭连接的。看看以下场景:

执行后,统计了下连接数,发现大量TIME_WAIT连接没有按预期回收,看来Response.Body.Close()没生效。

我们把代码调整如下:

再看看连接数统计:

为什么?以上是个较为特殊的场景,业务只关心请求的响应码,并不关心响应体,所以没有加入读取resp.Body的代码。可以看到此时关闭Body读取数据通道,会导致Golang底层没有真正关闭连接。要解决这个这种场景出现的连接泄露问题,需要在Close前额外加入io.Copy(ioutil.Discard, resp.Body),来完成TCP响应体读取流程。

Go语言未来的前景很不错,而在国内的大厂中,华为云对此的支持还是可以的,在其微服务应用平台、微服务引擎中开放了Go语言的服务框架。

目前,华为云有一个关于微服务的活动,有想应用服务微服务化需求的朋友可以考虑试用一下!

https://activity.huaweicloud.com/cse/index.html?dfk

使用Golang时遇到的一些坑的更多相关文章

  1. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(五)——实现注册功能

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  2. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(四)——对 run.py 的调整

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  3. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  4. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  5. 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(三)——使用Flask-Login库实现登录功能

    使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(一)——创建应用 使用 Flask 框架写用户登录功能的Demo时碰到的各种坑(二)——使用蓝图功能进行模块化 使用 Flask 框架写用 ...

  6. 记一次在node.js中使用crypto的createCipheriv方法进行加密时所遇到的坑

    Node.js的crypto模块提供了一组包括对OpenSSL的哈希.HMAC.加密.解密.签名,以及验证等一整套功能的封装.具体的使用方法可以参考这篇文章中的描述:node.js_crypto模块. ...

  7. 学习Spring5源码时所遇到的坑

    学习Spring5源码时所遇到的坑 0)本人下载的源码版本是 spring-framework-5.0.2.RELEASE 配置好gradle环境变量之后,cmd进入到spring项目,执行gradl ...

  8. 在PyQt5中使用Pandas时的几个坑

    最近在看Python GUI编程,在用到PyQt5+Pandas时遇到一些问题.这里把问题和解决方法整理一下.备查. (好像不能上传附件,内容只好写在下面了.) 在PyQt5中使用Pandas时的几个 ...

  9. golang 学习过程中踩的坑

    目录 [他人总结] 首字母大写才是对外可见的 包的初始化函数顺序问题 DB 连接泄漏问题 err 常用写法 goroutine 内的变量 指针可能是 nil 多层 map 未初始化 [他人总结] ht ...

随机推荐

  1. Python学习日记(三)——Python基本数据类型(运算符、int、str、tuple、dict、range)

    运算符 1.算数运算 2.比较运算 3.赋值运算 4.逻辑运算 5.成员运算 基本数据类型 1.数字 int(整型) 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2 ...

  2. Python经典练习题1:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

    Python经典练习题 网上能够搜得到的答案为: for i in range(1,85): if 168 % i == 0: j = 168 / i; if i > j and (i + j) ...

  3. [题解] [SDOI2015] 序列统计

    题面 题解 设 \(f[i][j]\) 代表长度为 \(i\) 的序列, 乘积模 \(m\) 为 \(j\) 的序列有多少个 转移方程如下 \[ f[i + j][C] = \sum_{A*B\equ ...

  4. 走进JavaWeb技术世界开篇:JavaWeb技术汇总

    微信公众号[Java技术江湖]一位阿里 Java 工程师的技术小站.(关注公众号后回复”Java“即可领取 Java基础.进阶.项目和架构师等免费学习资料,更有数据库.分布式.微服务等热门技术学习视频 ...

  5. 感知机算法及BP神经网络

    简介:感知机在1957年就已经提出,可以说是最为古老的分类方法之一了.是很多算法的鼻祖,比如说BP神经网络.虽然在今天看来它的分类模型在很多数时候泛化能力不强,但是它的原理却值得好好研究.先学好感知机 ...

  6. 五子棋AI教程

    https://github.com/Chuck-Ai/gobang 我写了非常详细的中文教程,教你如何一步步编写自己的五子棋AI: 五子棋AI设计教程第二版一:前言 五子棋AI设计教程第二版二:博弈 ...

  7. Flutter移动电商实战 --(31)列表页_列表切换交互制作

    点击左侧的大类右边的小类也跟着变化 新建provide 要改变哪里就建哪里的provide,我们现在要改变的是右边的商品列表的数组. category_goods_list.dart 这样我们的pro ...

  8. Web Service 实例基于Socket创建Web服务

    ServerSocket服务器端代码如下: public static void main(String[] args) throws IOException { // 1:建立服务器端的tcp so ...

  9. jquery 对svg 元素的addClass removeClass 支持

    jquery 2.2 之后才支持对svg 元素的addClass removeClass

  10. c++ vector容器自增长

    #include <iostream>#include <vector> using namespace std; int main(){ vector<int> ...