golang高级技巧

  • 22 浏览

rfyiamcool

2020/11/20 发布于 技术 分类

Go  Golang  go高级技巧 

文字内容
1. Golang ⾼级技巧 xiaorui.cc github.com/rfyiamcool v1
2. menu 基础配置 常见的坑 并发编程 效率库包 Q&A
3. 编码规范 字段对其, 注释对其 type User struct{ Username string // ⽤户名 Email string // 邮箱 type Scheme string URI string // 后缀 API string // 地址 IsOpen bool // 开放 CreateTime bool // 创建时间 const ( HTTP Scheme = "http" HTTPS Scheme = "https" ) } var ( isExist hasConflict canManage allowGitHook ) bool bool bool bool Bool使用”判断”语义的前缀 const ( ModeAdd ModeDel ModeUpdate ModeUpsert ) = iota + 1 自定义类型常量, iota从1开始
4. 编码规范 import ( "context" "crypto/tls" "fmt" "net/http" "time" "github.com/gin-gonic/gin" "git.xiaorui.cc/ocean/jellyfish/pkg/log" "git.xiaorui.cc/ocean/jellyfish/internal/api" "git.xiaorui.cc/ocean/jellyfish/internal/config" "git.xiaorui.cc/ocean/jellyfish/internal/middleware" ) 按照来源分段import type Option interface { // ... } func WithCache(c bool) Option { // ... } func WithLogger(log *zap.Logger) Option { // ... } // Open creates a connection. func Open(opts ...Option) (*Connection, error) { // ... } 动态参数
5. 编码规范 默认对象 const ( _defaultPort = 8080 defaultUser = "user" ) var ( ErrNotFound = errors.New(“not found”) ) 注意函数内做好语义拆分 type Handler struct { // ... } // ⽤于触发编译期的接⼝的合理性检查机制 // 如果Handler没有实现http.Handler,会在编译期报错 var _ http.Handler = (*Handler)(nil) func (h *Handler) ServeHTTP( w http.ResponseWriter, r *http.Request, ) { // ... } 不要try-catch那样使用panic 接⼝合理性检 代码要减少 if for 嵌套
6. 编码规范 var ( defaultGitlabClient *Client once = sync.Once{} ) // NewGitlabClient create gitlab client func NewGitlabClient(disfName string) (*Client, error) { once.Do(func() { defaultGitlabClient, err = newClient(disfName) }) return defaultGitlabClient, err type T struct { a int } // value receiver func (tv T) Mv(a int) { tv.a = 123 } // pointer receiver func (tp *T) Mp(f int) { tp.a = 123 } 值接收器 } 指针接收器 安全的单例 函数注释
7. Go⼯程目录 cmd api docs handler pkg router internal controller external service schema dao model … 这个目录吧 仁者见者, 智者见智 😅 开⼼就好
8. test Testify assert mock GoMock Monkey
9. 优雅退出 don’t catch sigkill (-9) process bind signal listen signal shutdown http grpc other tcp frame exit
10. 优雅重启 so_reuseport 直接开新进程也可进⾏listen 优雅关闭老进程 5. new client 7. when timeout, close 1. os/exec with listen fd process process os/exec新进程 3. sigterm 启动新⼆进制⽂件, 并传递listend fd 4. http.shutdown() 新进程载⼊listen fd, 开始接受请求 给老进程⼀个新信号,使其优雅退出 2. load and bind listen fd
11. makefile 统⼀执⾏⼊⼝ auto code format unit-test go lint build
12. version
13. gitflow master git merge hotfix git merge release/v1.0.0-rc.0 hotfix git checkout -b hotfix/fix-timeout master release git checkout -b release/v1.0.0-rc.0 develop develop … feature git checkout -b feature/add-timeout develop
14. major 主版本 不兼容的API的调整 semver not safe to update minor 次版本 new feature safe to update v1.0.2-alpha.1 v1.0.2-alpha.2 patch 修订版 bugfix safe to update v1.0.2-beta.1 v1.0.2-rc.1 pre-release label alpha 内部版本 beta 公测版本 rc 正式版本的候选版本 v1.0.2
15. 常见的坑 for range go net/http defer go in docker
16. for range go for range 遍历并发 局部对象 值传递给函数
17. net/http 修改默认的连接数 未读body则连接⽆法复用 未关闭io对象则协程泄露
18. defer retrun with defer 设置返回值 call defer list ret 匿名返回值 有名返回值 提前定义
19. cow CMPL JNE MOVQ MOVUPS MOVUPS MOVUPS MOVUPS MOVUPS MOVUPS MOVUPS MOVUPS . . . … runtime.writeBarrier(SB), $0 911 "".&m+64(SP), AX (AX), X0 X0, "".dict(SB) 16(AX), X0 X0, "".dict+16(SB) 32(AX), X0 X0, "".dict+32(SB) 48(AX), X0 X0, “".dict+48(SB)
20. go in docker P golang默认P的数量为取cpu core P P数的增多有何问题 ? P P P P P P 上下⽂切换开销 根据docker的cpu-quota来动态配置P P P cpu 64 core http://github.com/uber-go/automaxprocs
21. data race move 2 1 ⾼32bit 低32bit goroutine data race Data confusion get string set string int64 in 32bit system string solution copy and set mutex atomic store & load goroutine type structHeader struct { uintprt len }
22. 并发编程 同步原语 并发模型 atomic && cpu sync包 经验
23. 同步原语 Extend Sync mutex rwmutex ReentrantLock Semaphore SpinLock once Fslock cond atomic SingleFlight NetLocker
24. 通信 head channel 缓冲 ⽆缓冲 deque 两端都可处理 随意扩展 ringbuffer 有界实现 ⽆界实现 disruptor lock free tail
25. cpu cache read cache cache hit 从近到源读取 buf -> l1 -> l2 -> l3 -> mem cache miss 再从远到近逐步载⼊ main -> l3 -> l2 -> l1 wirte write through write back (主流) MESI ⼀致性协议 cacheline = 64 bytes register/buffer L1 L2 L3 memory 0 17.5 35 52.5 70
26. atomic 场景 并发 a = a + 1 add 轻量级, 减少futex锁竞争 cas spinlock 适合快锁逻辑 store cas 四次尝试 + cpu pause load runtime.gosched or osyield sleep 指令 { CMPXCHG } 可见性, 规避脏读 …
27. false sharing cache line Object A thread Object B thread c thread
28. pipeline producer worker worker worker worker worker
29. fan-out worker FAN-OUT模式 多个goroutine从同⼀个通道读取数据 扇出模式 producer worker 分发任务 worker
30. fan-in producer FAN-IN模式 producer consumer 1个goroutine从多个通道读取数据 扇⼊ producer
31. data race
32. context background context.Background() context.WithCancel() context context.WithTimeout() concel ctx context context.WithDeadline() context context.WithValue() context context context context
33. context request ctx 并发安全 函数之间数据及信号传递 goroutine background 协程指令传递 withCancel withTimeout withValue ctx ctx ctx goroutine goroutine ctx goroutine goroutine
34. defer 1.14 之前 defer 单次调用 ≈ 40ns 1.14 之后 ssa编译期间可优化defer
35. timer 升级go v1.10.3以上 runtime改进为p个timer定时器 升级到go v1.14.x 标准库timer 定时四叉堆收敛到p里面 严重的锁竞争 在findrunnable()时可触发 实现自定义时间轮 锁分散到每个槽位 使用map存储定时任务 损失精度来减少锁竞争 业务上允许低时间精度
36. timerWheel Ticker 按照刻度扫描 最⼤程度减少 锁冲突 !!! 回调队列 callBack caller struct timerEntry { map cas } callBack caller
37. 优化⼯具 为什么cpu开销⼤ ? 为什么这么多协程 ? pprof cpu on pprof cpu off use fgprof 协程都在⼲嘛 ? 排查死锁 ? 内存泄露点 ? pprof heap 内存优化点 ? gc 时延优化 ? pprof trace cpu-off 哪个⽅法慢 ? 时延⾼的函数
39. 经验 ⼀定要想好兜底 !!! fast fail 做好指标监控, 关注时延和QPS, 注意上线前后的cpu及mem 尽量在所有请求及逻辑中加⼊可靠的超时逻辑
40. 其他优化 sync.pool 对象缓冲 减少gc时延 sync.map 善用读写锁替换独占锁 使用连接池 适合读多写少的场景 适合缓存命中较多的场景 分段锁, 减少锁竞争 拆分channel, 提⾼管道的吞吐 预先分配合理的⼤小 (map slice) 使用可多路复用的协议 …
41. 效率库包 backoff ratelimiter gjson circuit breaker gops waitgroup cast cache retry gpool ……
42. ratelimiter 限流限频 令牌桶 可突增 (burst) golang.org/x/time/rate 漏桶 输出恒定 https://github.com/uber-go/ratelimit
43. circuit breaker 熔断器 失败 >= 阈值 close open 熔断时间窗⼝ 结束 失败 失败 < 阈值 or 成功 成功 half open https://github.com/sony/gobreaker https://github.com/rfyiamcool/easybreaker
44. waitgroup 扩展标准库 waitgroup merge errors easy api add timeout add context concurrency go func https://github.com/rfyiamcool/waitgroup
46. gpool 协程池 对上游调用流量整形 more stack 规避由协程暴增后,gc对gfree的影响 https://github.com/rfyiamcool/gpool
47. backoff 退避 1600 1200 800 400 0 1 2 https://github.com/rfyiamcool/backoff 3 4 5
48. retry 重试 each delay time backoff timeout times context recovery https://github.com/rfyiamcool/go-retry
49. gjson 模拟查找 ⽆需预先定义结构 就匹配查找 ! https://github.com/tidwall/gjson
50. gops 调试利器 base gops gops stack gops memstats gops stats … pprof gops pprof-cpu gops pprof-heap gops trace https://github.com/google/gops
51. cast 万能转换 丑陋的 `strconv` 类型转换 https://github.com/spf13/cast
53. “Q&A!” –峰云就她了