golang中的坑
slice
|
|
append
golang的append不是值拷贝,特别是在append函数入参的时候,尽量使用copy函数先处理一下再append,否则会踩很多坑。
slice的核心内容有两点:
- 函数为值复制传递
- slice的属性包含指向底层数组的指针、cap和len
结构体
结构体比较大小
|
|
mutex
最近在工作中发现有部分goroutine没有执行到的情况,而且非必现,在测试过程中没有出现该问题,上线后就出现了:dog: ,就是这么神奇。经过一番排查发现可能是mutex使用有问题,出现了死锁,因为该问题及其偶发,所以先增加了一个监控死锁的脚本定时判断是否出现死锁,同时针对可能的死锁进行了修改,查询了网上关于锁的注意事项在此整理。
golang的死锁监控
这部分参考了这篇文章,是通过pprof定时获取程序中的goroutine情况,检查其中是否存在sync.runtime_SemacquireMutex,它表示信号量阻塞在当前的gouroutine。出现这个信号不一定表示出现死锁,也可能是刚好处在等待锁的状态,只有长时间出现才会证明死锁了。
锁的使用注意
-
尽量减少锁的持有时间,不在持有锁期间进行IO操作
-
使用defer来进行锁的释放
-
适当时使用读写锁
-
copy结构体可能导致非预期的死锁!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
//copy结构体的时候,如果结构体中有锁,需要谨慎,多测试 package main import ( "fmt" "sync" ) type User struct { sync.Mutex name string } var UserArr = make(map[string]*User) func main() { UserArr["a"] = &User{ Mutex: sync.Mutex{}, name: "A", } test1 := UserArr["a"] test1.Lock() fmt.Println(test1.name) defer test1.Unlock() test2 := UserArr["a"] test2.Lock() //死锁,同一个锁对象,多次lock fmt.Println(test2.name) defer test2.Unlock() }
-
使用go vet检查锁的使用问题
-
使用 -race检查数据竞争
-
改为使用channel,减少锁的使用
-
针对读多写少的场景,使用sync.Map代替map加锁
Reference
https://mozillazg.com/2019/04/notes-about-go-lock-mutex.html
https://blog.csdn.net/u013536232/article/details/107868474
https://mp.weixin.qq.com/s/TzHvDdtfp0FZ9y1ndqeCRw
channel
无限缓存的channel
这是个学习channel,select用法的很好案例!!大力推荐
|
|
Reference
https://colobu.com/2021/05/11/unbounded-channel-in-go/
http
服务上线测试时主要观察的几点:
- 功能实现
- 关键日志和监控点
- cpu和内存使用情况
- 连接数和goroutine数量
今天测试上线了一个小服务,发现goroutine数量缓慢增长,tcp的CLOSE_WAIT数量也增加
pprof监控
|
|
http response.Body一定要close,只要client.Do不返回error,后面的response.Body都要close
当没有去read response Body的时候,可以通过一个CancelFunc去主动cancel掉
|
|
- 原文作者:nepp
- 原文链接:https://nepp-an.github.io/post/golang%E5%9D%91/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。