🧰 go-zero 常用库地图

go-zero 不只是 rest/zrpc 两个服务框架,它把「微服务要用的能力」拆成了一组 core/* 库。本文按「接入 / 治理 / 存储 / 基础」四层,逐一讲清每个库干啥的怎么用
记住:业务代码尽量只依赖 core/ 底层库,框架层(rest/zrpc)负责把它们编排进请求链路。

conf 配置logx 日志sqlx/cache/redis 存储 limit/breaker/load 治理syncx/mr 并发rest/zrpc 框架

一图看懂库的分层

上层依赖下层;请求从接入层进入,经过治理层,落到存储层,全程由基础层支撑。

接入层 · rest(HTTP)/ zrpc(gRPC) 对外暴露服务、路由、序列化、内置中间件链 治理层 · limit / breaker / load / discov 限流 · 熔断 · 自适应过载保护 · 服务发现(etcd) 存储层 · sqlx / cache / redis / mon 数据库访问 · 缓存封装 · 缓存击穿保护 · 文档库 基础层 · conf / logx / proc / syncx / mr / stat / prometheus / trace / bloom / collection 配置 · 日志 · 优雅退出 · 并发原语 · 指标 · 链路追踪 最常用 高并发必看 数据相关 无处不在
这套分层是 go-zero 的设计哲学:把「每个微服务都需要但写起来很烦」的能力(配置、日志、限流、熔断、缓存)做成独立库,框架把它接进请求链路,业务只管写 logic。

接入层 · 暴露服务

rest 提供 HTTP 服务,zrpc 提供 gRPC 服务,二者共享同一套配置 / 治理中间件。

rest HTTP 服务框架

干啥:基于 net/http 封装,加载 yaml 配置、注册路由、自动挂载 CORS / 超时 / 日志 / 熔断 / 限流等中间件,产出可直接 run 的 HTTP 服务。

var c rest.RestConf // 来自 conf.MustLoad 的配置 server := rest.MustNewServer(c, rest.WithCustomCors(nil, nil, "*")) defer server.Stop() server.AddRoutes([]rest.Route{{ Method: http.MethodGet, Path: "/ping", Handler: pingHandler, // func(http.ResponseWriter,*http.Request) }}) server.Start() // 阻塞监听
rest.MustNewServer
按配置建服务(失败 panic)。常用 option:WithCustomCors / WithUnauthorizedCallback
rest.ToMiddleware
http.HandlerFunc 包成 rest.Middleware,接入全局链。
rest.AddRoutes
批量注册路由;rest.WithMiddlewares 给部分路由加局部中间件。
rest.Handler
对单个 handler 应用内置中间件(超时/日志/熔断),返回标准 handler。
日常开发几乎不手写这些 —— goctl api go 已生成 main + handler + logic,你只填 logic。详见 go-zero-commands.html 与本目录 api 全流程。

zrpc gRPC 服务框架

干啥:基于 gRPC-go 封装,集成 etcd 服务发现、负载均衡、超时/熔断/限流/追踪拦截器。内部服务互相调用首选。

// 服务端 zrpc.MustNewServer(c.RpcServerConf, func(s *zrpc.RpcServer) { pb.RegisterUserServer(s.Server, user.NewUserServer(ctx)) }) // 客户端(从 etcd 发现并建连) client := zrpc.MustNewClient(c.RpcClientConf) userClient := pb.NewUserClient(client.Conn())
zrpc.MustNewServer
第二个参数是注册回调,把 pb 生成的 Server 挂上去。
zrpc.MustNewClient
Etcd / Target 配置自动发现节点,返回可建 Stub 的 Conn。
RpcServerConf
含 ListenOn、Etcd、Timeout、中间件开关。
client.Conn()
拿到 *grpc.ClientConn,用于 NewXxxClient。

zrpc/interceptor 拦截器(治理接入点)

干啥:go-zero 把限流/熔断/过载保护/追踪/指标做成 gRPC 拦截器,框架默认串好;也能手动显式加。

// 服务端额外拦截器 s := zrpc.NewServer(c, zrpc.WithUnaryServerInterceptor( interceptor.TimeoutInterceptor(3*time.Second))) // 客户端侧 zc := zrpc.MustNewClient(cc, zrpc.WithUnaryClientInterceptor( interceptor.BreakerInterceptor()))
拦截器作用
TimeoutInterceptor超时控制(配置 Timeout 自动生效)
BreakerInterceptor对下游调用做熔断
SheddingInterceptor自适应过载保护,拒绝时返回 过载
TracingInterceptorOpenTelemetry 链路追踪
PrometheusInterceptor暴露 QPS / 耗时指标
RecoverInterceptor捕获 panic 转 error,防进程崩

zrpc/resolver etcd 服务发现解析器

干啥:实现 gRPC resolver.Builder,让客户端按 etcd 里的 key 自动发现、监听、负载均衡后端节点。框架已内置,配置 Etcd 即生效;这里讲手动用法。

r := resolver.MustNewEtcdResolver([]string{"127.0.0.1:2379"}, "user.rpc", resolver.Direct) conn, _ := grpc.Dial("etcd:///"+r.Key(), grpc.WithResolvers(r))
绝大多数情况你不用手动调 resolver —— 在 zrpc 客户端配置里写 Etcd: {Hosts: [...], Key: "user.rpc"} 即可,框架自动注册 resolver。

治理层 · 高并发三件套

限流、熔断、过载保护。go-zero 把它们做成独立库,可脱离框架单独用。

core/limit 限流

干啥:两种算法,都依赖 redis 做分布式限流。PeriodLimit = 固定窗口(period 秒内容许 quota 次);TokenLimit = 令牌桶(rate 速率 / burst 突发)。

rds := redis.MustNewRedis(rc) l := limit.NewPeriodLimit(10, 100, rds, "rate:") // 10s 内 100 次 switch res, _ := l.Take("user:1"); res { case limit.Allow: fmt.Println("放行") case limit.Deny: fmt.Println("拒绝") } // 令牌桶 tb := limit.NewTokenLimit(10, 20, rds, "tok:")
为什么不能只在网关限流?网关是入口维度,业务里还要按「用户 / 接口 / 资源」精细限流,且要防单实例击穿。go-zero 把限流下沉到库,业务可随用随限。

core/breaker 熔断器

干啥:Google SRE 式熔断(错误率超阈值则打开,冷却后半开探活)。保护调用方不被下游拖垮。默认对下游调用自动熔断。

brk := breaker.NewBreaker(breaker.WithName("orderSvc")) resp, err := brk.Do(func() (any, error) { return callDownstream() }) if err != nil { // 熔断打开时 err = ErrServiceUnavailable return fallback() }
breaker.NewBreaker
可配 WithName / WithMaxAccept 等。
breaker.Do
执行请求;熔断打开直接走 err,不真打下游。

core/load 自适应过载保护

干啥:根据 CPU 与平均时延自适应「丢弃」请求,保护进程不雪崩。比固定阈值更聪明,go-zero 服务端默认开启。

shedder, _ := load.NewAdaptiveShedder() if err := shedder.Allow(); err != nil { return err // ErrServiceOverloaded,直接拒绝 } // 业务正常处理...
限流是「提前卡数量」,过载保护是「扛不住就丢」,熔断是「下游挂了别连」。三者互补,go-zero 默认全串在 zrpc/rest 的拦截器里。

core/discov 服务注册与发现

干啥:封装 etcd 的发布/订阅。Publisher 把自身地址写进 etcd;Subscriber 监听 key 变化,回调拿到最新节点列表。

p, _ := discov.NewPublisher(discov.EtcdConf{Hosts: []string{"127.0.0.1:2379"}}, "user.rpc", "127.0.0.1:8080") p.KeepAlive() // 心跳续租,进程退出自动摘掉 sub, _ := discov.NewSubscriber(etcd, "user.rpc") sub.AddListener(func(addrs []string) { fmt.Println("节点变化:", addrs) })
实际项目里服务发现交给 zrpc 配置 Etcd 自动完成,discov 多半用于定制注册逻辑或旁路监控。

存储层 · 数据访问

sqlx 访问数据库、cache 做缓存封装、redis 直接操作、三者协作防缓存击穿。

core/stores/sqlx SQL 访问

干啥:对 database/sql 的封装,统一 MySql / Pg / SqlServer 连接,提供 QueryRow / Exec / Transact,并自动接日志与慢查询统计。

conn := sqlx.NewMysql(dsn) // 或用 NewSqlConnFromConf var name string conn.QueryRow(&name, "select name from user where id=?", id) conn.Exec("insert into user(name) values(?)", "a") conn.Transact(func(s sqlx.Session) error { s.Exec("update account set bal=bal-?", 10) return nil })
NewMysql
直接传 DSN;生产用 NewSqlConnFromConf(c) 接配置文件。
QueryRow / QueryRowPartial
整行扫描 / 按列名部分扫描。
Transact
事务回调,返回 error 自动回滚。
与 goctl model
生成的 model 底层就是它,业务可直接拿 conn。

core/stores/cache 缓存封装

干啥:把「查缓存 → 没命中查库 → 回填」封装成 Take;内置 singleflight + 本地锁防缓存击穿,再上层可选 bloom 防穿透。

c := cache.New(cacheNodeConf) // 含 Redis 节点配置 var u User err := c.Take(&u, "user:1", func(v any) error { return conn.QueryRow(v, "select * from user where id=1") }) c.Del("user:1") // 写后删缓存
Take(v, key, queryFn) 是缓存层的灵魂:命中直接返回;未命中并发请求只放一个去查库并回填,其余共享结果 —— 这就是 singleflight 的价值。

core/stores/redis Redis 操作

干啥:对 go-redis/redigo 的封装(red 包),统一连接池、超时、错误处理。缓存层与限流底层都靠它。

r := redis.MustNewRedis(redis.RedisConf{ Host: "127.0.0.1:6379", Type: redis.NodeType, Pass: "", }) r.Set("k", "v") r.Setex("k", "v", 60) v, _ := r.Get("k") n, _ := r.Incr("cnt") r.Hget("h", "f")
MustNewRedis
配置失败 panic;Type 区分 Node / Cluster。
Setex / Incr / Hget
常用单值/计数/哈希操作一应俱全。
red.Redis 接口
可 mock 做测试,不绑死实现。
集群
RedisConf.Type=ClusterType 即走集群模式。

core/stores/mon MongoDB & core/bloom 布隆过滤器

mon:对 MongoDB 的封装(Collection 操作)。bloom:基于 redis 的布隆过滤器,挡掉「不存在的 key」打到数据库(缓存穿透)。

// 布隆:先问是否存在,不存在直接返回,避免透传到 DB b := bloom.New(bloomConf) if !b.Exists("user:999") { return nil, errNotFound // 一定不存在 } b.Add("user:1") // 写入时同步加
缓存三连击防护:击穿用 singleflight(cache.Take 内置)、穿透用 bloom、雪崩用随机过期时间。go-zero 全部备齐。

基础层 · 配置 / 日志 / 并发 / 观测

贯穿所有层的「横切」能力。最常用的是 conf、logx,其次是 syncx/mr 这类并发利器。

core/conf 配置加载

干啥:读 yaml/json 配置到结构体(注意:go-zero 用 json tag 映射字段)。支持环境变量覆盖、监听变更。

var c struct { Name string `json:"name"` Port int `json:"port"` } conf.MustLoad("etc/config.yaml", &c) // 失败 panic conf.Load("etc/config.yaml", &c, conf.UseEnv()) // 允许环境变量覆盖
坑:go-zero 配置文件字段映射用 json tag 不是 yaml tag。改了配置名记得同步改 struct 的 json tag,否则读到零值。

core/logx 日志

干啥:结构化日志(json 格式),分 Info/Error/Slow/Stat/Fatal 等级,自动带时间戳、调用方、traceId。替代自带 log。

logx.Info("server start") logx.Errorf("query failed: %v", err) logx.Slowf("slow sql: %s", sql) // 慢日志单独通道 logx.WithContext(ctx).Infof("req done") // 带上 traceId logx.SetUp(logx.LogConf{ServiceName: "user", Mode: "file"})
业务日志一律用 logx,别用 fmt.Println —— 这样日志能被采集、带 traceId、且框架的耗时/错误统计才接得上。

core/syncx 并发原语

干啥:一组「微信团队」打磨的并发工具。最神的是 SingleFlight(合并并发相同请求),还有 Pool、ResourceGroup、AtomicBool。

var sf syncx.SingleFlight val, err := sf.Do("key", func() (any, error) { return fetchExpensive() // 并发 100 次只真查 1 次 }) pool := syncx.NewPool(func() any { return new(bytes.Buffer) }) buf := pool.Take().(*bytes.Buffer) buf.Reset(); pool.Put(buf) // 用完归还
SingleFlight.Do
同 key 并发合并为一次执行,缓存击穿神器。
NewPool
对象池,类似 sync.Pool 但语义更清晰。
AtomicBool
无锁布尔,替代 bool+mutex。
ResourceGroup
一组资源共享生命周期,优雅释放。

core/mr MapReduce 并发聚合

干啥:把「扇出取数 + 聚合」写成 MapReduce,自动并发、自动 cancel、首个 error 即短路。批查多源数据的利器。

vals, err := mr.MapReduce( func(src chan<- int) { // generate for i := 0; i < 10; i++ { src <- i } }, func(item int, w mr.Writer[int], cancel func(error)) { v, e := fetch(item) // mapper(可并发) if e != nil { cancel(e); return } w.Write(v) }, func(pipe <-chan int, w mr.Writer[int], _ func(error)) { sum := 0 // reducer for v := range pipe { sum += v } w.Write(sum) }, ) mr.Finish(fn1, fn2, fn3) // 并发跑多个 fn,等全部,首个错返回
需要「并发拉 N 个数据源再汇总」时别手写 WaitGroup + 锁,用 mr.MapReduce / mr.Finish 更安全优雅。

core/proc 优雅退出 & core/collection 时间轮

proc:注册关闭钩子,收到信号时按序清理(关连接、flush 日志)。collection:TimingWheel(延迟任务)/ RollingWindow(滑动窗口指标)/ Cache(带 TTL 的内存缓存)。

proc.AddShutdownHandler(func() { db.Close(); logx.Close() // 进程退出前清理 }) // 时间轮:5s 一格、共 360 格 tw, _ := collection.NewTimingWheel(5*time.Second, 360, onExpire)
go-zero 框架已内置优雅退出(监听 SIGTERM)。只有当你自己 hold 了非托管资源(自连的 DB/自定义 goroutine)才需手动 AddShutdownHandler。

core/stat · core/prometheus · core/trace 可观测三件套

stat:自定义业务指标。prometheus:暴露 QPS/耗时到 /metrics。trace:基于 OpenTelemetry 的链路追踪,串起一次请求的上下游。

m := stat.NewMetrics("order_count") m.Add(1) // 业务计数 prometheus.Add("path", "/pay") // 打标签累加 trace.StartAgent(trace.Config{...}) // 启动 trace 上报 defer trace.StopAgent()
rest/zrpc 默认已接好 prometheus 与 tracing 拦截器。你要做的通常只是 stat.NewMetrics 加自己的业务埋点,再配好上报地址。

goctl · 代码生成 CLI

不是 runtime 库,但它是让上面所有库「自动用起来」的发动机。

干啥:goctl 读 .api / .proto / .sql,生成带 rest+zrpc+model+配置+中间件 的整套骨架。生成的代码内部就调用了本页所有库(conf.MustLoad、sqlx、cache、limit 拦截器等)。

goctl api go -api user.api -dir . # 生成 HTTP 服务 goctl rpc protoc user.proto --zrpc_out=. -m # 生成 RPC 服务 goctl model mysql ddl -src user.sql -dir . -c # 生成带缓存 model
想记住完整命令?本目录已有 go-zero-commands.html 专门速查 goctl。本文聚焦「库本身」,命令请移步那篇。

速查总表

一眼定位:这个能力去哪个库找。

我想做…用哪个库入口函数
起 HTTP 服务restMustNewServer / AddRoutes / Start
起 gRPC 服务 / 调内部服务zrpcMustNewServer / MustNewClient
接 trace/熔断/超时中间件zrpc/interceptorTimeoutInterceptor / BreakerInterceptor
服务发现zrpc/resolver / discovMustNewEtcdResolver / NewPublisher
限流core/limitNewPeriodLimit / NewTokenLimit
熔断core/breakerNewBreaker().Do
过载保护core/loadNewAdaptiveShedder().Allow
访问 MySQLcore/stores/sqlxNewMysql / QueryRow / Exec / Transact
缓存封装(防击穿)core/stores/cacheNew().Take / Del
操作 Rediscore/stores/redisMustNewRedis / Set / Get / Incr
防缓存穿透core/bloomNew().Add / Exists
读配置core/confMustLoad / Load
打日志core/logxInfo / Errorf / Slowf / WithContext
合并并发请求core/syncxSingleFlight.Do / NewPool
并发聚合多源core/mrMapReduce / Finish
优雅退出core/procAddShutdownHandler
业务指标 / 监控 / 追踪core/stat·prometheus·traceNewMetrics / Add / StartAgent
生成全套代码goctl(CLI)api go / rpc protoc / model
记忆法:框架(rest/zrpc)负责编排,core/* 负责能力,goctl 负责生成。业务代码通常只碰 logic + svc + 几个 core/* 工具库。