Go 入门和深入

Go语言入门和深入

Go 常用框架(工具)技术雷达 ❤️

技术选型一般选择接口稳定,持续维护,生态相对成熟,star 数量较高,用户广泛的库,坑少一点。 前后分离时代用 gin 之类的框架写app后台还是挺快的,但是感觉做并发不高的内部后台业务还是用脚本python/php之类的更快。 以下第三方库均可以通过 google + 关键词搜索到,同一行尽量按照流行程度从前往后列举,默认都是 github 上的包(只写了仓库后缀)。 也可以去 awesome-go 之类的去查找,然后根据 star 数目等作为参考选用。

  • web/rpc框架: gin, grpc, beego, labstack/echo

  • 微服务框架:go-kit, go-micro, karatos(b 站),go-zero(好未来),jupiter(斗鱼)

  • 参数验证:go-playground/validator, bytedance/go-tagexpr

  • 单元测试断言:matryer/is, testify/assert, smartystreets/goconvey(bdd 驱动测试), rakyll/gotest(gotest 颜色)

  • 错误处理: pkg/errors, hashicorp/go-multierror(多错误处理), sync/errgroup(多goroutine错误处理)

  • panic处理:thepkg/recover

  • 重试:avast/retry-go

  • json处理转换:go-simplejson/mapstructure,json-iterator/go (比内置的 json 解析快很多), tidwall/gjson(获取 json 值), bytedance/sonic

  • 字典/结构体合并/结构体拷贝/类型转换:imdario/mergo, jinzhu/copier, jmattheis/goverter

  • 配置解析: viper(兼容很多格式)

  • mysql orm: gorm, xorm, sqlx, ent/ent(实体框架), doug-martin/goqu(生成sql)

  • redis: go-redis, redigo

  • Kafka: Shopify/sarama, confluent-kafka-go

  • Elasticsearch: olivere/elastic, elastic/go-elasticsearch

  • mongodb: mongodb/mongo-go-driver

  • id生成器: rx/xid, beinan/fastid, bwmarrin/snowflake, sony/sonyflake, godruoyi/go-snowflake

  • uuid: gofrs/uuid, satori/go.uuid, google/uuid (注意有些会 panic)

  • hash: cespare/xxhash(快速 hash), groupcache/consistenthash(一致性哈希)

  • cache(in memory并发安全): patrickmn/go-cache, allegro/bigcache, golang/groupcache(分布式), coocood/freecache, singleflight(防止缓存击穿), dgraph-io/ristretto, orcaman/concurrent-map(泛型)

  • cache(基于context): ag9920/go-ctxcache (基于context缓存解决重复调用放大问题)

  • cache(lru/lfu/2Q/ARC): hashicorp/golang-lru, bluele/gcache, songangweb/mcache(增强lru)

  • 并发/协程池(star 数从低到高排序):

  • 原子访问:uber-go/atomic

  • 异步任务队列框架: machinery, gocelery, hibiken/asynq, LMSTFY(美图开源)

  • 分布式/定时任务: robfig/cron, ouiqiang/gocron, distribworks/dkon, shunfei/cronsun

  • 熔断:hystrix-go, eapache/go-resiliency, cep21/circuit, alibaba/sentinel-golang

  • 限流库:

    • web框架限流:ulule/limiter, didip/tollbooth

    • 令牌桶(token bucket)限流:juju/ratelimit, golang.org/x/time/rate

    • 漏桶(leaky bucket)限流: uber-go/ratelimit

  • 日志: logrus, zap, lumberjack(滚动日志)

  • 链路追踪:opentracing/opentracing-go, uber/jaeger-client-go

  • 调试:go-spew/dlv, kr/pretty

  • 图片处理:h2non/imaginary

  • 网络库/连接池:fatih/pool; panjf2000/gnet, valyala/fasthttp,kavu/go_reuseport

  • websocket: nhooyr.io/websocket, gorilla/websocket

  • http client: levigross/grequests, asmcos/requests, go-resty/resty, gojek/heimdall(重试、熔断)

  • 表格:go-echarts

  • excel(XLSX): 360EntSecGroup-Skylar/excelize, tealeg/xlsx

  • 转换工具:

  • 代码检查工具:

    • 静态检查:golangci-lint

    • goroutine 泄露检查: github.com/uber-go/goleak

    • 注释工具: github.com/cuonglm/gocmt 自动给导出变量、函数等增加注释

  • 热编译工具:gowatch

  • 网络代理:goproxy

  • 命令行处理: spf13/pflag, spf13/cobra

  • 字符串处理工具:huandu/xstrings

  • 通用数据类型转换:spf13/cast

  • HTML 处理/过滤: PuerkitoBio/goquery, microcosm-cc/bluemonday

  • 系统信息收集:shirou/gopsutil

  • go runtime: bmhatfield/go-runtime-metrics(runtime 指标收集)

  • 邮件:gopkg.in/gomail

  • 接口文档生成:swaggo/swag

  • 消息队列:nsqio/nsq

  • 延时队列/时间轮:ouqiang/delay-queue, RussellLuo/timingwheel

  • 分布式kv存储:etcd

  • 用户认证:golang-jwt/jwt,dgrijalva/jwt-go(弃用), authelia/authelia

  • 访问(权限)控制:casbin/casbin

  • 进程控制:uber-go/automaxprocs

  • 地理位置:ip2location/ip2location-go

  • 时间处理:jinzhu/now

  • 金融数字格式化/定点数: leekchan/accounting, shopspring/decimal

  • 分布式事务:yedf/dtm

  • 分布式锁: go-redsync/redsync(redlock算法), bsm/redislock, go-zero/core/stores/redis

  • Zookeeper: go-zookeeper/zk

  • 设计模式:tmrts/go-patterns

  • 数据结构:deckarep/golang-set, emirpasic/gods

  • 通用泛型工具库:thoas/go-funk

  • 通用工具库:duke-git/lancet

  • 深拷贝:mohae/deepcopy, barkimedes/go-deepcopy

  • 采样监控:mosn/holmes(排查OOM等问题)

  • 规则引擎:govaluate, goengine, gorule, diegoholiveira/jsonlogic (基于json存储和解析规则)

工具:

Go Books

Go 开发工具

  • Goland IDE

  • Vscode/Sublime/Atom 等常用编辑器结合插件

  • vim/Neovim + vim-go + coc.nvim

博客:

Go 博客教程

Go 设计模式

Go idioms

Go 错误处理

Go日志实践

Go文档查询

GOPROXY 代理

如果有有一些库拉不下来又没有自己的代理,可以试试

export GOPROXY=https://goproxy.io

Web/RPC框架

  • gin

  • grpc

个人推荐使用 gin,当然你可以参考一下 star 选择别的框架

Gin example

gin 实战博客:

微服务

微服务框架:

微服务代码示例:

Go package (搜索常用的 go 第三方库)

Go项目Layout

单元测试(unittest)

GoMock框架使用指南 如何写出优雅的 golang 代码

静态语言编写单测相比动态语言要难一些,动态语言中比如 python 可以很容易用 mock.patch 来做属性/方法替换。 但是静态语言不行,一般难点在于如何去模拟外部依赖(比如数据库/rpc请求,redis 请求等):

  • 接口(go 推荐面向接口编程,否则你很难使用 gomock 来编写单测)

  • mysql: 如何 mock 数据库请求。使用 sqlmock,或者编写 dao 层 interface,然后 mock 这个dao层接口

  • http: 使用 httpmock 来模拟请求返回值

  • redis: 这里我试了下 miniredis 比较好用,基于 go 实现,无需真实的 redis server

也有一种方式在单测环境加入真实的db 和redis(比如 docker),然后单测读取测试环境的数据库来操作。 这样的好处是可以不使用各种 mock 库,直接操作真实的 mysql,测试代码写起来也更方便。

以下是一些单测相关的库:

  • testing: 内置库

  • github.com/stretchr/testify/assert: 用来做断言 assert 方便

  • gomock(mockgen): 静态语言难以像动态语言直接属性替换,所以一般我们基于接口编写代码,然后可以生成接口 mock

  • sqlmock: 如果依赖了数据库 mysql 等,可以使用 sqlmock 模拟数据库返回内容。(或者就在测试环境用真实的 mysql,测试完清理插入的测试数据)

  • httpmock: 用来 mock 调 http 请求

  • github.com/alicebob/miniredis 可以用来 mock redis,无需启动真实的 resdis server。试了下非常好用,也不用使用 mock 和真实的 redis 了。个人强烈推荐

  • bouk/monkey: 通过替换函数指针的方式修改任意函数的实现,如果以上都无法满足需求,可以用这种比较 hack 的方式。可能需要禁止编译器内联优化 go test -gcflask=-l ./...

  • agiledragon/gomonkey: go 语言实现 monkey patch

目前比较推荐使用 assert 做断言,使用 gomonkey 用来 mock 函数/方法等。

参考:

Go 断点调试器dlv

# 搜索函数,打断点,如果有同名函数的时候比较有用
funcs FuncName

# 打断点断点
b main.main

# 打印变量
print val

# go get -u github.com/derekparker/delve/cmd/dlv
dlv debug main.go

# 加上命令行参数
# https://github.com/go-delve/delve/issues/562
dlv debug ./cmd/unit-assignment-cli/main.go -- server

# 如何调试 go 的 coredump 文件。对于一些很偶发的进程退出会比较难排查,可以利用 coredump 文件辅助排查问题:
1. 调整ulimit关于core file size的设置,执行 ulimit -c unlimited 将core file size设成无限大小。
2. 输出环境变量 export GOTRACEBACK=crash 使得golang进程知道需要产生cash时候的coredump文件。
3. 分析 /usr/local/bin/dlv core ./app ./core_app
4. 使用命令 goroutine goroutineid  bt 打印栈信息

# dlv 常用命令:
break main.go:7  # 在main.go 第 7 行加入断点
break runtime.growslice # 函数处打断点
continue # 继续执行运行到断点处
disassemble # 插件对应的反汇编代码
goroutines # 查看当前 goroutines
stack(bt) # 查看调用栈信息
regs  # 过regs命令可以查看全部的寄存器状态, 可以通过单步执行来观察寄存器的变化
locals # 查看当前函数所有变量值

Go 跨平台编译

用 Go 你可以选择自己喜欢的操作系统开发,并跨平台编译程序要发布平台的可执行程序即可。 Go 通过两个环境变量控制跨平台编译:

  • GOOS: 代表要编译的目标操作系统,常见的有 Linux, Windows, Darwin 等

  • GOARCH: 代表要编译的目标处理器架构,常见的有 386, AMD64, ARM64 等

比如现在在用 macOS AMD64 开发,但是想要编译出 Linux AMD64 的可执行程序,只需要执行:

GOOS=linux GOARCH=amd64 go build main.go

Go Debug 调试工具

Go vs. Python

Go Best practice(工程实践)

Go 开发关键技术指南

Go 常用命令

# 获取 go 的 import 列表 (list import)
# https://pmcgrath.net/how-to-get-golang-package-import-list
go list -f '{{range $imp := .Imports}}{{printf "%s\n" $imp}}{{end}}' | sort
go list -f '{{range $dep := .Deps}}{{printf "%s\n" $dep}}{{end}}' | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}'

# 清理模块缓存, GO111MODULE=on 以后,下载的模块内容会缓存在$GOPATH/pkg/mod 目录中: 使用以下命令可清空缓存:
go clean --modcache

# 跨平台编译
`GOOS=linux GOARCH=amd64 go build main.go`

# 强制重新构建(依赖包) 使用 -a。参考:http://c.biancheng.net/view/120.html
go build -a main.go

# go mod graph
# 会显示出go.mod里需要的每个包,都依赖了哪些包。可以用这个工具可视化 https://github.com/PaulXu-cn/go-mod-graph-chart
go get -u github.com/PaulXu-cn/go-mod-graph-chart/gmchart
go mod graph | gmchart

# remove any unused package
go mod tidy -v

Go 数据结构与算法

博客:

Go 底层实现(源码)

Go Profiler

Go 性能优化

Goroutines

Go 内存泄露(memory leak)

Go 反射

Go 网络编程

Go 操作消息队列

Go 并发模式

Go 位操作

Go 缺陷

Go Leetcode

Go 面试题

Go源码阅读

除了内置库之外,go 还有很多优秀的源码值得学习。建议用到的一些优秀的第三方库的源码都可以看一下,了解底层实现也方便排查问题。

../_images/gocode%E9%98%85%E8%AF%BB.png