Go-Kratos 入门实战:从零实现用户 CRUD 服务
【摘要】 🌟 一、Kratos 是什么?为什么选它?Kratos 是由 Bilibili 开源、社区共建的 Go 微服务开发框架,目标是让开发者专注于业务逻辑,不被基础设施拖累。 ✅ 四大核心优势能力说明技术实现Microservices独立部署、独立演进模块化布局 + 服务注册发现Specified API统一 API 定义Protobuf + 自动生成 HTTP/gRPC 接口Plug-abl...
🌟 一、Kratos 是什么?为什么选它?
Kratos 是由 Bilibili 开源、社区共建的 Go 微服务开发框架,目标是让开发者专注于业务逻辑,不被基础设施拖累。
✅ 四大核心优势
| 能力 | 说明 | 技术实现 |
|---|---|---|
| Microservices | 独立部署、独立演进 | 模块化布局 + 服务注册发现 |
| Specified API | 统一 API 定义 | Protobuf + 自动生成 HTTP/gRPC 接口 |
| Plug-able | 插件化扩展 | Tracing/Metrics/Log/RateLimit 按需装配 |
💡 一句话理解:
Kratos = Protobuf First + Clean Architecture + Cloud Native Ready
🛠️ 二、环境准备(含国内加速)
1. 安装 Go(≥ v1.23)
go version
# 推荐:1.24+
2. 安装 Kratos CLI
# 国外源(可能慢)
go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
# ✅ 国内推荐:Gitee 源(更快)
go install -v github.com/go-kratos/kratos/cmd/kratos/v2@latest
# 若拉取失败,可手动设置 GOPROXY
export GOPROXY=https://goproxy.cn,direct
3. 安装 Protobuf 编译器 & 插件
# macOS
brew install protobuf
# Ubuntu
sudo apt install -y protobuf-compiler
# 安装 Go 插件(关键!)
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2@latest
✅ 验证安装:
kratos -v
# 输出示例:kratos version v2.7.2
🧱 三、创建项目骨架
# 使用 Gitee 源(国内友好)
kratos new user-service -r https://gitee.com/go-kratos/kratos-layout.git
cd user-service
go mod tidy
生成目录结构(精简关键部分):
user-service/
├── api/ # ← Protobuf API 定义
├── cmd/
│ └── user-service/ # ← 启动入口
├── internal/
│ ├── biz/ # ← 业务逻辑(UseCase)
│ ├── data/ # ← 数据访问(Repo/DB)
│ ├── service/ # ← 服务实现(对接 API)
│ └── server/ # ← HTTP/gRPC 服务注册
├── go.mod
└── Makefile
💡 布局理念:Clean Architecture 分层
API → Service → Biz → Data,依赖方向内聚,测试友好。
📝 四、定义用户 API(Protobuf)
1. 添加 Proto 文件
kratos proto add api/user/v1/user.proto
编辑 api/user/v1/user.proto:
syntax = "proto3";
package api.user.v1;
option go_package = "user-service/api/user/v1;v1";
import "google/api/annotations.proto";
import "errors/errors.proto"; // ← 启用自定义错误
// 用户实体
message User {
int64 id = 1;
string name = 2;
string email = 3;
int32 age = 4;
}
// 请求/响应
message CreateUserRequest {
string name = 1;
string email = 2;
int32 age = 3;
}
message CreateUserReply { User user = 1; }
message GetUserRequest { int64 id = 1; }
message GetUserReply { User user = 1; }
message UpdateUserRequest {
int64 id = 1;
string name = 2;
string email = 3;
int32 age = 4;
}
message UpdateUserReply { User user = 1; }
message DeleteUserRequest { int64 id = 1; }
message DeleteUserReply { bool ok = 1; }
message ListUserRequest { int32 page = 1; int32 size = 2; }
message ListUserReply { repeated User users = 1; }
// 错误定义(关键!)
extend google.protobuf.MethodOptions {
kratos.api.Errors errors = 1111;
}
service UserService {
rpc CreateUser(CreateUserRequest) returns (CreateUserReply) {
option (google.api.http) = {
post: "/v1/users"
body: "*"
};
}
rpc GetUser(GetUserRequest) returns (GetUserReply) {
option (google.api.http) = {
get: "/v1/users/{id}"
};
option (errors) = {
rpc_error: [{
code: 404,
reason: "USER_NOT_FOUND",
message: "user not found"
}];
};
}
rpc UpdateUser(UpdateUserRequest) returns (UpdateUserReply) {
option (google.api.http) = {
put: "/v1/users/{id}",
body: "*"
};
}
rpc DeleteUser(DeleteUserRequest) returns (DeleteUserReply) {
option (google.api.http) = {
delete: "/v1/users/{id}"
};
}
rpc ListUser(ListUserRequest) returns (ListUserReply) {
option (google.api.http) = {
get: "/v1/users"
};
}
}
🔍 关键点:
google.api.http:自动生成 RESTful 路由errors/errors.proto+option (errors):生成类型安全的错误构造器(如v1.ErrorUserNotFound().Err())
🧩 五、生成代码(Protobuf → Go)
# 或手动执行
kratos proto client api/user/v1/user.proto
生成文件:
api/user/v1/
├── user.pb.go # Protobuf 序列化
├── user_grpc.pb.go # gRPC 服务桩
└── user_http.pb.go # HTTP 路由绑定(含参数解析)
✅ 此时 HTTP/gRPC 双协议接口已自动生成,无需手写路由!
💼 六、分层实现:CRUD 逻辑
1. 定义业务模型 & 接口(internal/biz/user.go)
package biz
import "context"
type User struct {
ID int64
Name string
Email string
Age int32
}
// 仓库接口(Repo)
type UserRepo interface {
Save(ctx context.Context, u *User) (*User, error)
Get(ctx context.Context, id int64) (*User, error)
Update(ctx context.Context, u *User) (*User, error)
Delete(ctx context.Context, id int64) error
List(ctx context.Context, page, size int32) ([]*User, error)
}
// 用例层(UseCase)
type UserUsecase struct {
repo UserRepo
}
func NewUserUsecase(repo UserRepo) *UserUsecase {
return &UserUsecase{repo: repo}
}
func (uc *UserUsecase) Create(ctx context.Context, u *User) (*User, error) {
return uc.repo.Save(ctx, u)
}
func (uc *UserUsecase) Get(ctx context.Context, id int64) (*User, error) {
u, err := uc.repo.Get(ctx, id)
if err != nil {
return nil, err
}
if u == nil {
return nil, v1.ErrorUserNotFound("user not found").Err() // ← 类型安全错误
}
return u, nil
}
// Update/Delete/List 略(结构类似)
2. 实现数据层(内存模拟)—— internal/data/user.go
package data
import (
"context"
"sync/atomic"
"user-service/internal/biz"
)
type userRepo struct {
data map[int64]*biz.User
seq int64
}
func NewUserRepo() biz.UserRepo {
return &userRepo{
data: make(map[int64]*biz.User),
}
}
func (r *userRepo) Save(ctx context.Context, u *biz.User) (*biz.User, error) {
id := atomic.AddInt64(&r.seq, 1)
u.ID = id
r.data[id] = u
return u, nil
}
func (r *userRepo) Get(ctx context.Context, id int64) (*biz.User, error) {
u, ok := r.data[id]
if !ok {
return nil, nil // not found
}
return u, nil
}
func (r *userRepo) Update(ctx context.Context, u *biz.User) (*biz.User, error) {
if _, exists := r.data[u.ID]; !exists {
return nil, nil
}
r.data[u.ID] = u
return u, nil
}
func (r *userRepo) Delete(ctx context.Context, id int64) error {
delete(r.data, id)
return nil
}
func (r *userRepo) List(ctx context.Context, page, size int32) ([]*biz.User, error) {
var users []*biz.User
for _, u := range r.data {
users = append(users, u)
}
return users, nil
}
🔔 实际项目请替换为 GORM / Ent / sqlx + MySQL/PostgreSQL
3. 实现 Service 层(对接 API)—— internal/service/user.go
# 生成骨架(可选)
kratos proto server api/user/v1/user.proto -t internal/service
完善 internal/service/user.go:
package service
import (
"context"
"user-service/api/user/v1"
"user-service/internal/biz"
)
type UserService struct {
v1.UnimplementedUserServiceServer // ← 嵌入未实现桩,避免漏方法
uc *biz.UserUsecase
}
func NewUserService(uc *biz.UserUsecase) *UserService {
return &UserService{uc: uc}
}
func (s *UserService) CreateUser(ctx context.Context, req *v1.CreateUserRequest) (*v1.CreateUserReply, error) {
u := &biz.User{
Name: req.Name,
Email: req.Email,
Age: req.Age,
}
created, err := s.uc.Create(ctx, u)
if err != nil {
return nil, err
}
return &v1.CreateUserReply{
User: convertUser(created),
}, nil
}
func (s *UserService) GetUser(ctx context.Context, req *v1.GetUserRequest) (*v1.GetUserReply, error) {
u, err := s.uc.Get(ctx, req.Id)
if err != nil {
return nil, err
}
return &v1.GetUserReply{
User: convertUser(u),
}, nil
}
// 辅助转换函数
func convertUser(u *biz.User) *v1.User {
return &v1.User{
Id: u.ID,
Name: u.Name,
Email: u.Email,
Age: u.Age,
}
}
// UpdateUser/DeleteUser/ListUser 略(类似)
⚙️ 七、注册服务 & 启动
1. 修改 internal/server/http.go
// 在 NewHTTPServer 中添加:
v1.RegisterUserServiceHTTPServer(srv, service.NewUserService(uc))
2. 修改 internal/server/grpc.go
// 在 NewGRPCServer 中添加:
v1.RegisterUserServiceServer(srv, service.NewUserService(uc))
3. 初始化依赖
// 在 main() 中:
repo := data.NewUserRepo()
uc := biz.NewUserUsecase(repo)
svc := service.NewUserService(uc)
// HTTP & gRPC server 启动时传入 svc
app := kratos.New(
kratos.Name("user-service"),
kratos.Server(
httpSrv,
grpcSrv,
),
)
✅ 推荐使用 Wire 依赖注入(模板已生成
wire.go),避免手动 new。
▶️ 八、运行 & 测试
# 启动服务
go run ./cmd/user-service
# 默认端口:
# HTTP: :8000
# gRPC: :9000
🔧 使用 curl 测试(HTTP)
# 创建
curl -X POST http://localhost:8000/v1/users \
-H "Content-Type: application/json" \
-d '{"name":"Tom","email":"tom@example.com","age":30}'
# → {"user":{"id":1,"name":"Tom","email":"tom@example.com","age":30}}
# 获取
curl http://localhost:8000/v1/users/1
# 更新
curl -X PUT http://localhost:8000/v1/users/1 \
-d '{"name":"Tom Lee","age":31}'
# 列表
curl "http://localhost:8000/v1/users?page=1&size=10"
# 删除
curl -X DELETE http://localhost:8000/v1/users/1
📚 总结
| 步骤 | 命令/操作 |
|---|---|
| 创建项目 | kratos new user-service -r https://gitee.com/... |
| 定义 API | 编写 user.proto |
| 生成代码 | make api 或 kratos proto client ... |
| 实现逻辑 | biz → data → service |
| 启动测试 | go run ./cmd/... + curl |
✅ 你已掌握:
- Kratos 核心开发流程
- Protobuf First 工作流
- HTTP & gRPC 双协议服务
- 分层架构(Clean Architecture)
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)