kratos 的 http/grpc 查询入口依赖 .proto 文件中定义的 rpc 方法,必须严格匹配服务方法签名和 google.api.http option 配置,路径参数自动映射到请求消息字段,查询参数需显式定义在 message 中。

查询接口定义必须匹配proto服务方法签名
Kratos 的 HTTP/gRPC 查询入口依赖 .proto 文件中定义的 RPC 方法,不是写个 handler 就能查。如果你在 service.proto 里声明了 rpc GetUser(GetUserRequest) returns (GetUserResponse);,那对应的服务实现就必须有同名 Go 方法,且参数和返回值类型严格对应生成的 *v1.GetUserRequest 和 *v1.GetUserResponse。
常见错误是手写 HTTP handler 绕过 proto 定义,结果路由注册成功但 gRPC 端无法调用,或者 OpenAPI 文档缺失字段。Kratos 默认用 transport/http.NewServer 自动绑定 HTTPRule,前提是你的 google.api.http option 写对了:
rpc GetUser(GetUserRequest) returns (GetUserResponse) {
option (google.api.http) = {
get: "/v1/users/{id}"
};
}
- 路径参数
{id}会自动映射到GetUserRequest.Id字段,字段名必须一致(大小写敏感) - 查询参数如
?page=1&size=10需要显式定义在GetUserRequestmessage 中,不能靠 middleware 解析 - 不加
google.api.httpoption 的 RPC 方法,默认不会暴露为 HTTP 接口
数据库查询逻辑应放在 data 层,而非 service
Kratos 推荐分层:service 处理协议转换和业务编排,data 层封装数据访问。直接在 service 里写 db.QueryRow(...) 看似快,但会导致单元测试难写、事务难控制、SQL 散落各处。
正确做法是定义 data.UserRepo 接口,在 data 包内实现 userRepo 结构体,用 sqlx 或 ent 执行查询。例如:
func (r *userRepo) GetUser(ctx context.Context, id uint64) (*User, error) {
var u User
err := r.db.GetContext(ctx, &u, "SELECT id, name, email FROM users WHERE id = ?", id)
return &u, err
}
-
data层只返回领域模型(如*User),不暴露*v1.User这类 DTO - SQL 错误需转成 Kratos 标准错误(如
errors.NotFound),避免把sql.ErrNoRows直接抛给 service - 如果用 ent,记得在
ent.Generate后更新data层的 repo 实现,别手动改 ent 生成的代码
service 层做请求校验和 DTO 转换,别塞业务逻辑
很多开发者把权限判断、状态机流转、缓存刷新全堆进 service 方法里,导致它又重又难测。Kratos 的 service 应该轻量——只做三件事:校验输入、调用 data 层、组装响应。
例如 GetUser service 方法应长这样:
func (s *UserService) GetUser(ctx context.Context, req *v1.GetUserRequest) (*v1.GetUserResponse, error) {
if req.Id == 0 {
return nil, errors.BadRequest("USER_NOT_FOUND", "id cannot be zero")
}
u, err := s.userRepo.GetUser(ctx, uint64(req.Id))
if err != nil {
return nil, err // 已由 data 层转为标准错误
}
return &v1.GetUserResponse{User: &v1.User{Id: u.ID, Name: u.Name}}, nil
}
- 校验失败用
errors.BadRequest/errors.NotFound,不要用fmt.Errorf - DTO 转换建议用
mapstructure或手写(小结构体手写更可控),避免反射开销和运行时 panic - 别在 service 里调
cache.Set或mq.Publish,那是biz或job层的事
调试时优先看 kratos run 启动日志和 HTTP 404/500 响应体
Kratos 启动失败或接口 404,往往不是代码逻辑错,而是配置或生成环节断了。先盯住终端输出:
- 没看到
HTTP server started on [::]:8000?检查cmd/server/main.go里是否漏了http.NewServer(...)注册 - 访问
/swagger404?确认transport/http.NewServer是否传入了http.WithMiddleware()里包含swag.Handler - POST
/v1/users返回 500 且无 body?加log.WithContext(ctx).Errorw("get user failed", "err", err)到 service 方法末尾,看日志是否打出真实错误 - gRPC 调不通但 HTTP 可以?检查
transport/grpc.NewServer是否注册了对应 service,以及客户端是否用了正确的 proto service 名
真正容易被忽略的是 proto 文件修改后忘记重新 kratos proto client 和 kratos proto server —— 生成代码没更新,service 方法签名和 DTO 就会不匹配,运行时报 panic 或字段为空。











