kratos.new() 启动 panic 的根本原因是基础初始化缺失三要素:未在 main() 开头调用 conf.load() 注册配置源、未创建 http/grpc.server 实例、未将实例传入 kratos.new() 的 server 参数列表。

kratos.New() 一启动就 panic,不是代码写错了,是基础初始化漏了三件事:没加载配置、没创建 server 实例、没传进 kratos.New()。
conf.Load() 必须在 main() 开头调用,否则 kratos.New() 直接崩溃
kratos.New() 内部会主动触发配置加载,但默认没注册任何 config.Provider。它不报“找不到 app.yaml”,而是直接 panic: no config provider registered —— 这个错误不提示路径,也不给上下文,纯靠经验定位。
- 必须在
main()函数第一行就调用conf.Load(),不能等日志初始化完或 flag 解析后再做 -
conf.Load()需要显式传入至少一个config.Provider,比如config.NewFile("configs/app.yaml")或config.NewJson(`{"name":"demo"}`) - 别依赖环境变量自动替换:
os.Getenv("CONFIG_PATH")得自己拼进config.NewFile(),kratos 不解析$CONFIG_PATH - 如果
configs/app.yaml不存在,c.Load()会返回 error,必须检查,否则后续 panic 更难追
service.Register() 报 rpc error: code = Unavailable 是因为 grpc.Server 没启或没注入
service.Register() 不是向远程服务注册,而是向本进程内已运行的 grpc.Server 实例注册。它失败,说明你根本没创建 grpc.Server,或者创建了但没传给 kratos.New()。
- 确认是否调用了
grpc.NewServer(),且返回值非 nil(比如 consul 连不上时consul.New()可能返回 nil + error,只判 error 会漏掉实例) - 确认
grpc.Server实例已加入kratos.New(kratos.Server(httpSrv, grpcSrv))的参数列表;漏传grpcSrv就等于没启 gRPC - 监听地址别写
localhost:9000:某些容器或 CI 环境下localhost解析失败,改用0.0.0.0:9000 - 如果项目压根不用 gRPC,就别调
service.Register()—— HTTP 路由完全独立,不需要它也能跑通 REST 接口
proto 编译后没有 RegisterXXXServiceServer 方法,缺的是 protoc-gen-go-grpc 插件
Kratos 的 gRPC 服务注册函数(如 RegisterDeviceServiceServer)不是 protoc-gen-go 生成的,必须用 protoc-gen-go-grpc(v2 版本)和 protoc-gen-go-http 两个插件一起生成。
- 单独装
protoc-gen-go只生成*.pb.go,不生成 gRPC Server 注册函数和 HTTP 映射逻辑 - 命令必须带
paths=source_relative:例如protoc --go-grpc_out=paths=source_relative:. device.proto,否则生成路径错乱,RegisterXXXServiceServer会出现在错误包里 -
.proto文件顶部的option go_package必须和生成后文件的package xxx严格一致,否则 import 失败,RegisterXXXServiceServer在别处定义也等于没定义 - 字段类型不能写
float:proto3 不支持,必须明确为float32或float64
HTTP 中间件里 ctx.Value() 拿不到值,是因为没把值塞进 request.Context()
Kratos 的 HTTP server 基于标准 net/http,中间件链中的 ctx 来自 http.Request.Context()。你用 context.WithValue(context.Background(), key, val) 创建的 context 和请求生命周期无关,自然取不到。
- 要在中间件中透传数据,必须用
req = req.WithContext(context.WithValue(req.Context(), key, val)),再调next.ServeHTTP(w, req) - 别依赖
transport.HTTPContext()—— 它返回的是空 context,不关联 request;要用的是transport.HTTPRequestContext()(注意名字差一个词) - 如果 handler 里用
transport.FromServerContext(r.Context())提取 transport info,确保中间件没覆盖掉原始 context
最常被忽略的其实是顺序:conf.Load() → 构建 server 实例 → kratos.New() → app.Run()。中间任意一步返回 nil 且没检查,panic 就藏在堆栈深处,看着像框架问题,实际只是初始化链条断了一环。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











