kratos.New() panic 根源是 wire 未生成或未注入 conf.Load 所需的 provider,常见于 wire.Build 缺失 NewConfig 等 provider 或 wire.Struct 配置错误;service.Register 报 Unavailable 因 *grpc.Server 为 nil;proto 无 Register 方法因缺失 protoc-gen-go-grpc 和 protoc-gen-go-http 插件。

kratos.New() 启动 panic 不是代码写错了,而是 wire 生成的依赖注入代码没生效,或根本没生成 —— 最常见原因是 wire.Build 没包含所有 provider,或 wire.NewSet 漏掉了关键依赖。
为什么 wire.Gen 之后还是报 “no config provider registered”
这个 panic 实际发生在 kratos.New() 内部,但它根源不在 kratos,而在 wire 生成的初始化函数没把 conf.Load() 所需的 provider 注入进去。
-
conf.Load()必须在main()第一行调用,但它本身不创建 provider;provider 是你用config.NewFile("configs/app.yaml")这类函数显式构造的 - wire 要求所有 provider(比如
NewConfig、NewServer、NewData)必须被wire.NewSet显式聚合,再传给wire.Build - 如果
internal/di/provider.go里漏写了wire.NewSet(NewConfig),或者NewConfig函数签名返回了*conf.Conf, error但没加wire.Struct(new(conf.Conf), "*"),conf.Load()就拿不到实例,直接 panic - 别信“wire 会自动扫描”,它只认你白纸黑字写进
wire.Build的那些函数和集合
service.Register() 报 rpc error: code = Unavailable 的真实原因
这不是网络问题,也不是服务没起来,而是 service.Register() 调用时,传进去的 *grpc.Server 是 nil —— 根本没被 wire 构造出来,或构造失败后没处理 error。
- 检查
NewGRPCServer()是否返回了非 nil 的*grpc.Server;某些场景下(比如 consul 初始化失败),consul.New()可能返回nil, err,但你只判了err != nil,漏掉了对返回值的空检查 -
service.Register()必须在grpc.Server实例创建完成、且已加入kratos.New(kratos.Server(httpSrv, grpcSrv))参数列表之后才能调用;顺序错或漏传都会导致注册失败 - 如果你压根不用 gRPC,就别调
service.Register()—— HTTP 接口完全独立,不需要它也能跑通
proto 编译后没有 RegisterXXXServiceServer 方法
不是 protoc 命令写错了,是插件链不完整:只装了 protoc-gen-go,没装 protoc-gen-go-grpc(v2)和 protoc-gen-go-http。
-
protoc-gen-go(v1)只生成*.pb.go,不生成 server 注册函数,也不生成 HTTP 路由映射逻辑 -
protoc-gen-go-grpc(v2)才生成RegisterXXXServiceServer和UnimplementedXXXServiceServer -
protoc-gen-go-http负责解析google.api.http注解,生成HTTPToGRPC路由表;缺它,REST 接口就 404 - 确认
make api或手动 protoc 命令里同时指定了--go-grpc_out和--go-http_out,路径参数也得对(比如--go-grpc_opt=paths=source_relative)
Wire 的核心约束很朴素:每个 provider 函数必须可被静态分析到,每个依赖类型必须有且仅有一个 provider 返回它。一旦出现类型冲突(比如两个函数都返回 *sql.DB)、或 provider 缺失(比如 NewLogger 没放进 wire.NewSet),生成阶段就会报错 —— 这不是 bug,是设计使然。别绕过它去手写初始化,那等于放弃编译期检查。











