wth2jhl.online

Back

📘 原文信息

  • 项目名:Kratos(go-kratos/kratos)
  • 副标题:A Go framework for microservices
  • 作者:Kratos 团队(哔哩哔哩 / Bilibili 开源)+ 社区贡献者
  • 当前版本:v3.x(master 分支,2026 年活跃维护)
  • 首发日期:约 2019 年(v1/v2 历史)
  • 仓库:https://github.com/go-kratos/kratos ↗
  • 官网:https://go-kratos.dev ↗
  • 文档:https://go-kratos.dev/docs/getting-started/start ↗
  • License:MIT
  • 总规模:8.7MB(depth 1 clone),321 个 .go 文件,约 45,357 行(含 contrib),主仓约 29,000 行
  • 核心依赖:Go 1.25+、log/slog(标准库)、google.golang.org/grpc、google.golang.org/protobuf、gorilla/mux v1.8.1、gorilla/websocket v1.5.3、google/uuid、fsnotify、golang.org/x/sync/errgroup
  • 本次分析版本:基于 master 分支(depth 1 clone)

一、为什么这篇值得读?#

如果说 Gin 是 Go Web 框架的事实标准(单进程 HTTP 服务器),那么 Kratos 就是 Go 微服务框架的代表——一个完整的”服务 + 协议 + 中间件 + 注册中心 + 配置 + 编码 + 日志”的全栈解决方案。

截至 2026 年,Kratos 在 GitHub 上 24k+ ⭐,被哔哩哔哩(B站)内部大规模生产使用,也是少数几个真正解决了”多协议 + 多注册中心 + 可观测性”的痛点的 Go 框架。

它和 Gin 的差异不在于”哪个更好”,而在于关注点完全不同:

维度GinKratos
核心定位HTTP Web 框架微服务全栈框架
协议HTTP/1, HTTP/2 h2c, HTTP/3HTTP + gRPC(原生)
服务发现�✅ registry(consul/etcd/polaris/nacos/…)
配置中心❌✅ config(file/env/etcd/apollo/…)
错误体系简单 c.JSONGoogle API errors + gRPC status + Reason
中间件粒度全局 / 路由分组按 selector 路由(/helloworld.v1.Greeter/SayHello)
代码生成�✅ kratos proto + protoc-gen-go-http/errors
可观测性由中间件提供✅ tracing + metrics(OpenTelemetry)内置
学习曲线半天上手1-2 周

读 Kratos v3 的源码,会带你理解真正的微服务框架需要解决哪些问题——这些问题是 Gin 设计者不需要面对的,但生产级服务必须面对。


二、用户视角:Kratos 提供什么?#

2.1 能力地图#

模块提供者入口
应用生命周期kratos.Appkratos.New(opts...) + app.Run()
HTTP transporttransport/http.Serverhttp.NewServer(...)
gRPC transporttransport/grpc.Servergrpc.NewServer(...)
统一 transport 抽象transport.Server/Transportertransport.FromServerContext(ctx)
中间件middleware/*.Middlewaremiddleware.Chain(...)
错误体系errors.Errorerrors.BadRequest(...)
编码encoding/{json,xml,yaml,proto,form,protojson}encoding.GetCodec("json")
日志log/slog(标准库)log.With(...)
元数据metadata.Metadatametadata.New(ctx, md)
服务注册/发现registry.Registrarkratos.Registrar(etcd)
配置中心config.Sourceconfig.New(...config.WithSource(file))
健康检查grpc_health_v1(gRPC 内置)s.health.Resume()/Shutdown()
反射reflection.Register(gRPC 内置)自动开启
代码生成cmd/kratos + cmd/protoc-gen-go-errors/httpprotoc ...

2.2 一段 Kratos Hello World#

这一段代码里就有 5 层抽象:App(生命周期)→ Server 接口 → HTTP Server + gRPC Server(实现)→ transport.Server 接口(统一)。


三、架构全景:模块依赖图#

关键设计原则:

  • App 不感知协议——只调用 transport.Server.Start(ctx)/Stop(ctx);
  • middleware 不感知协议——func(Handler) Handler 与 HTTP/gRPC 都兼容;
  • codec/encoding 用 init 注册——加新格式只需 import _ 一行;
  • 配置 / 注册 / 错误 都走接口抽象——config.Source、registry.Registrar、errors.Error。

四、源码拆解·Part 1:App 生命周期 — errgroup 的教科书用法#

4.1 app.go(215 行)— 整个框架的入口#

Functional Options 模式 —— 和 Gin v1.9+ 一样,这是 Go 生态的事实标准。

4.2 App.Run() 的 errgroup 编排#

这段代码的精妙之处:

  1. errgroup.WithContext — 任一 goroutine 返回 error,自动 cancel 共享 ctx,所有 goroutine 都退出;
  2. 每个 server 跑两个 goroutine:Start 一个(阻塞到 ctx.Done)、Stop 一个(监听 ctx.Done 后触发)。这是 Kubernetes Pod 同款模式——主进程 + sidecar;
  3. wg.Wait() 在 Register 之前——确保 server 已绑定端口再注册,否则注册中心可能把流量路由到还没 listen 的实例;
  4. signal.Notify(c, a.opts.sigs...) 进 errgroup——信号也是 errgroup 成员,统一编排;
  5. stopTimeout + context.WithoutCancel(octx) — 优雅退出有超时,超时后用 WithoutCancel 避免父 ctx 已 cancel 影响子 ctx。

这是 Go 后端服务最标准的”主循环 + 优雅退出”范式,值得每篇 Go 微服务博客都抄一遍。

4.3 App.Stop() 与 buildInstance()#

关键技巧:srv.(transport.Endpointer) 类型断言——如果 server 实现了 Endpoint() (*url.URL, error),就自动拿到真实地址。这就是”鸭子类型 + 接口隔离”的优雅。


五、源码拆解·Part 2:transport.Server — 协议无关的统一接口#

5.1 整个 transport 的核心接口(transport/transport.go,89 行)#

这是 Kratos 抽象最值钱的部分 —— 整个中间件系统、错误系统、日志系统都基于这套接口工作。一旦你写了:

ctx := transport.NewServerContext(ctx, transporter)
go

那么中间件里就能 transport.FromServerContext(ctx) 拿到 transport,完全不用关心是 HTTP 还是 gRPC。

5.2 初始化时强制注册所有 codec#

// transport/transport.go 顶部
package transport

import (
    _ "github.com/go-kratos/kratos/v3/encoding/form"
    _ "github.com/go-kratos/kratos/v3/encoding/json"
    _ "github.com/go-kratos/kratos/v3/encoding/proto"
    _ "github.com/go-kratos/kratos/v3/encoding/protojson"
    _ "github.com/go-kratos/kratos/v3/encoding/xml"
    _ "github.com/go-kratos/kratos/v3/encoding/yaml"
)
go

这是个非常隐蔽但极重要的设计 —— transport 包 import 了所有 encoding 包,只是为了触发它们的 init() 函数。

每个 encoding 子包的 init 大致是这样(encoding/json/codec.go):

func init() {
    encoding.RegisterCodec(jsonCodec{})
}

type jsonCodec struct{}

func (jsonCodec) Marshal(v any) ([]byte, error) { ... }
func (jsonCodec) Unmarshal(data []byte, v any) error { ... }
go

好处:

  • 用户不用手动 import 各种 codec;
  • encoding.GetCodec("json") 直接能用;
  • 加新 codec 只需在 encoding/ 下建一个子包 + import _。

六、源码拆解·Part 3:transport/http.Server(368 行)#

6.1 整体结构#

3 个接口断言 —— Server 同时实现 transport.Server(生命周期)、transport.Endpointer(拿 URL)、http.Handler(被 JCEF/反代嵌入)。这是接口隔离原则的实践。

6.2 filter() 是请求的”前置装饰”#

关键设计:

  • 统一超时:context.WithTimeout(req.Context(), s.timeout),每个请求都受 server-level timeout 控制;
  • path template 替换:/path/123 转 /path/{id} —— 这是 gRPC operation 的命名空间规范;
  • transport 注入:把 Transport 对象通过 context.WithValue 注入 ctx,中间件可随时拿到。

6.3 路由:用的是 gorilla/mux,不是 httprouter#

router:      mux.NewRouter(),
srv.router.Use(srv.filter())
go

v3 改用 gorilla/mux,不再用 httprouter。原因:

  • gorilla/mux 支持子路由器(PathPrefix().Subrouter());
  • 支持header matcher(Headers("Content-Type", "application/json"));
  • 支持自定义 NotFoundHandler / MethodNotAllowedHandler;
  • 性能虽不如 httprouter,但功能完备性更高,更适合 RPC 场景。

6.4 WalkRoute 与 WalkHandle — OpenAPI 生成的基础#

func (s *Server) WalkRoute(fn WalkRouteFunc) error {
    return s.router.Walk(func(route *mux.Route, _ *mux.Router, _ []*mux.Route) error {
        methods, _ := route.GetMethods()
        path, _ := route.GetPathTemplate()
        for _, method := range methods {
            if err := fn(RouteInfo{Method: method, Path: path}); err != nil { return err }
        }
        return nil
    })
}
go

遍历所有注册的路由 —— 这是 kratos proto 生成 OpenAPI/Swagger 文档、注册中心服务发现、Pprof endpoint 注册的基础。

6.5 Start / Stop 与 listenAndEndpoint#

优雅退出双保险:Shutdown(ctx) 等连接排空;超时后强制 Close() —— Kubernetes Pod 终止时滚出窗口期(默认 30 秒)内必须退出。


七、源码拆解·Part 4:transport/grpc.Server(267 行)#

7.1 整体结构#

和 HTTP Server 几乎完全平行 —— middleware/streamMiddleware 都用同一个 matcher.Matcher,意味着一套中间件既适用于 HTTP 又适用于 gRPC。

7.2 NewServer 的内部拦截器链#

亮点:

  • 第一位置插入自己的 unaryServerInterceptor —— Kratos 把 Kratos 中间件挂在 gRPC 拦截器链的最前面,先于用户配置的拦截器;
  • 健康检查、reflection、admin 全部默认注册 —— 不需要用户手动调用;
  • adminClean 函数保留 —— Stop 时需要调用以清理 admin 资源。

7.3 unaryServerInterceptor — Kratos 中间件与 gRPC 的粘合剂#

精妙之处:

  • s.middleware.Match(tr.Operation()) —— 根据 gRPC full method(比如 /helloworld.Greeter/SayHello)匹配应该应用哪些中间件;
  • 然后手动构造 Kratos 中间件链,最后调用 handler(即 gRPC 的真实方法);
  • 这就是 “Kratos middleware 与 grpc-go interceptor 二者并存”的实现。

7.4 优雅退出(goroutine + select)#

和 HTTP 的优雅退出套路一样 —— GracefulStop 阻塞,ctx.Done() 触发强制 Stop()。Kubernetes 30 秒终止窗口期下,这套机制能保证不丢正在处理的请求。


八、源码拆解·Part 5:middleware — 协议无关 + selector 路由#

8.1 中间件定义(middleware/middleware.go,36 行)#

type Handler func(ctx context.Context, req any) (any, error)

type Middleware func(Handler) Handler

func Chain(m ...Middleware) Middleware {
    return func(next Handler) Handler {
        for i := len(m) - 1; i >= 0; i-- {
            next = m[i](next)
        }
        return next
    }
}
go

这是整个中间件系统最值钱的部分 —— 3 行代码,没有任何 HTTP/gRPC 的影子。

和 Gin 的对比:

GinKratos
func(c *gin.Context)func(ctx context.Context, req any) (any, error)
协议特定(HTTP)协议无关
中间件按路由分组(前缀)按 selector 路由(method-level)
通过 c.Next() 链式调用返回 (Handler) Handler 函数式
顺序在 routergroup 里硬编码由 matcher.Matcher 动态决定

Kratos 的中间件可以这么写(协议无关):

func Tracing() middleware.Middleware {
    return func(handler middleware.Handler) middleware.Handler {
        return func(ctx context.Context, req any) (any, error) {
            tr := otel.Tracer("svc")
            ctx, span := tr.Start(ctx, "call")
            defer span.End()
            return handler(ctx, req)
        }
    }
}
go

这段代码既能给 HTTP 用,也能给 gRPC 用 —— 因为它只依赖 ctx 和 req 两个抽象。

8.2 matcher.Matcher — 按 selector 路由中间件#

// internal/matcher/matcher.go(简化)
type Matcher struct {
    root *node
}

func (m *Matcher) Add(pattern string, ms ...middleware.Middleware) { ... }
func (m *Matcher) Match(operation string) []middleware.Middleware { ... }
go

Selector 支持 3 种形式:

s.Use("/*", loggingMiddleware())                                  // 所有路由
s.Use("/helloworld.v1.Greeter/*", authMiddleware())               // 整个 service
s.Use("/helloworld.v1.Greeter/SayHello", rateLimitMiddleware())   // 单个方法
go

这是和 Gin 完全不同的设计 —— 粒度精确到 gRPC method。这在大型服务里非常重要:

  • /User/Login 走 rate-limit + captcha;
  • /User/UpdateProfile 走 auth + audit;
  • 其它路由走基础 middleware。

8.3 recovery 中间件示例#

亮点:

  • 用标准库 log/slog(slog.ErrorContext 带 ctx tracing);
  • runtime.Stack(buf, false) 抓堆栈;
  • Functional Options(WithHandler / WithLogger)定制 panic 处理函数;
  • 不带 ctx 的恢复点也带上 —— logger.ErrorContext(ctx, ...) 让 OpenTelemetry 能关联 panic 与 trace。

九、源码拆解·Part 6:errors — Google API errors 体系#

9.1 errors.Error 设计#

关键设计:

  • Status 复用 google.golang.org/genproto/googleapis/api/errdetails —— 这是 Google API errors 标准,所有 GCP / Google Cloud SDK 都用这套;
  • GRPCStatus() 实现 status.Status 接口 —— gRPC 调用 status.FromError(err) 能拿到正确 code;
  • Code(err) 自动从 HTTP 转 gRPC —— httpstatus.ToGRPCCode(int(e.Code)) 把 HTTP 404 转 gRPC NOT_FOUND。

9.2 HTTP/gRPC 错误编码自动互通#

这是 Kratos 的杀手锏 —— 业务代码只需 return errors.BadRequest("USER_NOT_FOUND", "user not found"),HTTP 端返回 400 + JSON,gRPC 端返回 INVALID_ARGUMENT + ErrorInfo。一套错误体系,两个协议。

9.3 errors.BadRequest / errors.InternalServer / errors.NotFound#

func BadRequest(reason, message string) *Error { return New(400, reason, message) }
func InternalServer(reason, message string) *Error { return New(500, reason, message) }
func NotFound(reason, message string) *Error { return New(404, reason, message) }
func Errorf(code int, reason, format string, a ...any) error { return New(code, reason, fmt.Sprintf(format, a...)) }
go

和 Gin 的 c.JSON(400, gin.H{"error": ...}) 对比:

  • Gin:任意结构,前端要单独写解析;
  • Kratos:标准化的 {code, reason, message, metadata} 字段,前端可以直接写通用的错误处理函数。

十、源码拆解·Part 7:encoding — init 注册的 codec 工厂#

10.1 codec 接口(encoding/encoding.go)#

type Codec interface {
    Marshal(v any) ([]byte, error)
    Unmarshal(data []byte, v any) error
    Name() string
}

var codecs = map[string]Codec{}

func RegisterCodec(codec Codec) {
    if codec.Name() == "" { panic("cannot register codec with empty name") }
    codecs[strings.ToLower(codec.Name())] = codec
}

func GetCodec(name string) Codec { return codecs[name] }
go

最简单的 registry 模式 —— 全局 map + init 时注册。

10.2 JSON codec(encoding/json/codec.go)#

package json

import "encoding/json"

func init() { encoding.RegisterCodec(jsonCodec{}) }

type jsonCodec struct{}

func (jsonCodec) Marshal(v any) ([]byte, error)   { return json.Marshal(v) }
func (jsonCodec) Unmarshal(data []byte, v any) error { return json.Unmarshal(data, v) }
func (jsonCodec) Name() string                       { return "json" }
go

极致简洁 —— 一行 init,三个方法,搞定 JSON 支持。

10.3 protojson — 专门为 Protobuf 而生#

protojson 用 google.golang.org/protobuf/encoding/protojson,字段名自动转 camelCase(JSON 规范)+ 保留 Protobuf 数字类型(int64 不转 float64)+ 支持 oneof / map / 嵌套 message。

这个 codec 对 API 互操作极重要 —— Protobuf 服务直接用 JSON 通信而无需生成新的结构体。

10.4 protoc-gen-go-http 与 protoc-gen-go-errors 代码生成#

# 生成 HTTP handler
protoc --go-http_out=. api/helloworld.proto

# 生成 errors
protoc --go-errors_out=. api/errors.proto
bash

生成的代码大致是这样:

// helloworld_http.pb.go(自动生成)
var _Greeter_SayHello_HTTP_Handler = func(srv helloworld.GreeterServer, w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
    var in helloworld.HelloRequest
    if err := binding.JSON.BindHTTP(req, &in); err != nil {
        codec.JSON.Marshal(w, httperror.Error(400, "INVALID_ARGUMENT", err.Error()))
        return
    }
    out, err := srv.SayHello(req.Context(), &in)
    if err != nil {
        codec.JSON.Marshal(w, httpstatus.FromError(err))
        return
    }
    codec.JSON.Marshal(w, out)
}
go

业务代码只需要实现 Protobuf interface(纯业务逻辑),HTTP/gRPC 协议层完全自动生成。这是 “API-first” 的极致实践。


十一、源码拆解·Part 8:internal/ — 看似小但极关键的内部包#

11.1 internal/host — 0.0.0.0 转真实 IP#

K8s Pod 监听 0.0.0.0:8080 时,要注册到注册中心,需要真实可访问的 IP(10.0.0.5:8080)。internal/host/host.go:

func Extract(address string, lis net.Listener) (string, error) {
    addr, err := parseAddress(address, lis)
    if err != nil { return "", err }
    // 1. 如果是 IPv4 / IPv6 specific,直接返回
    // 2. 如果是 0.0.0.0,遍历所有 interface,按规则(POD_IP env / hostname / 网卡顺序)挑一个
    // 3. 在 K8s 里,优先用 status.podIP
    ...
}
go

这是 K8s 部署微服务的必修课 —— 注册中心不知道你是 0.0.0.0,但客户端需要真实 IP。

11.2 internal/matcher — 中间件的 selector 路由#

// 类似 gin 的前缀树,但支持 3 种 selector:
// 1. /*        - 任意
// 2. /svc/*    - service 级别
// 3. /svc/method - method 级别
go

11.3 internal/endpoint — scheme://host:port 构造#

func NewEndpoint(scheme, addr string) *url.URL {
    return &url.URL{Scheme: scheme, Host: addr}
}
go

简化了 URL 构造 —— 同时支持 http://127.0.0.1:8000、grpc://127.0.0.1:9000、discovery:///provider-demo 三种 scheme。


十二、设计哲学:它做对了什么?#

读完 4.5 万行代码,我提炼 Kratos v3 的几条核心原则:

12.1 “协议无关” — 整套抽象基于 transport.Server + func(Handler) Handler#

这是 Kratos 最值钱的设计。App 不知道底下是 HTTP 还是 gRPC,中间件不知道调用是 HTTP 还是 gRPC,errors 自动适配两个协议。

对比 Gin —— Gin 整个生命周期绑定 HTTP,要做 gRPC 得用 grpc-go,两套中间件写两遍。Kratos 一套写两边用。

12.2 “Functional Options 模式” — 字段爆炸的解药#

kratos.New(
    kratos.Name("helloworld"),
    kratos.Version("v1.0.0"),
    kratos.Server(httpSrv, grpcSrv),
    kratos.Logger(myLogger),
    kratos.Registrar(etcdReg),
    kratos.RegistrarTimeout(10*time.Second),
    kratos.StopTimeout(15*time.Second),
    kratos.BeforeStart(func(ctx context.Context) error { ... }),
    kratos.AfterStop(func(ctx context.Context) error { ... }),
)
go

对比构造器 / setter —— Functional Options 在 Go 生态已经成为事实标准,Go 1.18+ 还支持泛型 Option。

12.3 “errgroup 编排” — 多 server 多 goroutine 的标准范式#

App.Run() 的实现是 Go 服务主循环的教科书:

  • 每个 server 一个 Start goroutine + 一个 Stop goroutine;
  • errgroup.WithContext 自动级联退出;
  • 信号监听也是 errgroup 成员;
  • wg.Wait() 确保 server listen 后才注册。

12.4 “init 注册” — 加新 codec 只需一行 import#

import _ "github.com/go-kratos/kratos/v3/encoding/protojson"
go

零侵入 + 零配置 —— 这是 Go 的 init() 机制独有的优雅。

12.5 “Google API errors” — 错误体系标准化#

{code, reason, message, metadata} 四元组,HTTP 和 gRPC 自动互通,前端可以写通用的错误处理函数。

12.6 “API-first + 代码生成” — Protobuf 一处定义#

kratos proto add api/helloworld/helloworld.proto
kratos proto client api/helloworld/helloworld.proto      # 生成 client
kratos proto server api/helloworld/helloworld.proto -t internal/service  # 生成 server interface
go generate ./...                                        # 一键生成
bash

业务代码只剩 Protobuf interface 的实现 —— HTTP handler、gRPC handler、错误码、OpenAPI 文档全部自动生成。


十三、设计哲学:它没做对的事?#

  1. 文档分散在 docs/ + 官网 + examples 仓库 —— 没有一站式入口,新手难上手;
  2. protoc-gen-go-http/errors 需要 protoc 工具链 —— 不像 Gin 直接 go run 就行;
  3. v3 依赖 gorilla/mux 替代了 httprouter —— 性能略降,功能更全;
  4. internal/matcher 不是公共 API —— 但很多项目实际需要 selector 路由,只能自己 fork;
  5. 没有 WebSocket/HTTP/2 长连接的 helper —— WebSocket 在 contrib 里;
  6. 错误码与 Reason 重复 —— code=400 是 HTTP 状态,reason=USER_NOT_FOUND 是业务错误,但 gRPC 走的是 INVALID_ARGUMENT,两套语义需要学习成本;
  7. 没有 Context 的”中间件作用域”概念 —— 所有中间件共享一个 chain,粒度只在 selector 层。

十四、给学习者的阅读路径#

如果你想理解 Go 微服务框架的设计,推荐阅读顺序:

  1. app.go + options.go —— 30 分钟,理解 App 生命周期 + Functional Options;
  2. transport/transport.go —— 20 分钟,理解协议无关抽象;
  3. transport/http/server.go + transport/grpc/server.go —— 1 小时,并排对比 HTTP 和 gRPC 的实现差异;
  4. middleware/middleware.go + internal/matcher/matcher.go —— 1 小时,理解协议无关中间件 + selector 路由;
  5. errors/errors.go + transport/http/status/ —— 1 小时,理解 Google API errors 体系;
  6. encoding/encoding.go + encoding/json/codec.go —— 20 分钟,理解 init 注册的 codec 模式;
  7. internal/host/host.go —— 30 分钟,K8s 部署必备;
  8. cmd/kratos —— 浏览 CLI 实现;
  9. cmd/protoc-gen-go-http + cmd/protoc-gen-go-errors —— 1 小时,理解代码生成的代码长什么样;
  10. contrib/ —— 浏览 otel/polaris/opensergo 等生态。

十五、附录:文件规模与模块分布#


十六、Kratos vs Gin 怎么选?#

场景推荐原因
个人项目 / 中小 APIGin简单,半天上手
单体服务Gin不需要 gRPC、注册中心
微服务(多协议 + 注册中心)Kratos一站式
K8s 原生部署KratosPOD_IP、graceful shutdown、admin
需要 OpenAPI 自动生成Kratosprotoc-gen-go-http
需要 tracing + metrics 一体化Kratoscontrib/otel
极致 HTTP 性能Gin零分配路由
内部 RPC 服务(不暴露 HTTP)KratosgRPC + protobuf + 一套错误
想学框架设计两个都读Gin 学”单协议极致”,Kratos 学”多协议抽象”

最终建议:如果你正在做 Go 微服务,Kratos 是当前最完整的开源选择;如果你做 Web API / BFF,Gin 还是更顺手。


十七、参考资料#


写在最后#

Kratos v3 不是 Gin 的”升级版” —— 它们解决不同维度的问题。Gin 把 HTTP 做到极致,Kratos 把”协议无关 + 微服务全栈”做到极致。

读 Kratos 源码,真正值得学的不是某个 API,而是它对抽象边界的清晰划分:

  • App 管生命周期(不知道协议)
  • transport.Server 是协议接口
  • middleware 是协议无关(只依赖 ctx 和 req)
  • errors 自动适配多协议
  • encoding 通过 init 注册
  • registry 是接口,consul/etcd/polaris 是实现
  • config 是接口,file/env/etcd 是实现

当你也要做 Go 框架时,先想清楚”哪些必须协议无关”——这就是 Kratos 4.5 万行代码的最大公约数。

深入解析 Kratos v3:哔哩哔哩(B站)开源的 Go 微服务框架是怎么设计的
https://wth2jhl.online/blog/kratos-v3-microservice-framework-architecture/
Author 小吴同学
Published at August 10, 2026