1、简介
Kratos 一套轻量级 Go 微服务框架,包含大量微服务相关框架及工具
2、示例
2.1、准备条件
mac 为例
go : 安装go1.23.6
protoc : 直接 brew install protobuf
2.2、官网示例
https://go-kratos.dev/docs/getting-started/start
2.2.1、安装kratos
go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
2.2.2、下载helloworld示例
kratos new helloworld
2.2.3、安装依赖
make init
2.2.4、生成代码
make all
2.2.5、IDEA运行
-conf /Users/xxx/IdeaProjects/helloworld/configs/config.yaml
2.2.6、命令行运行
kratos run
2.3、访问
curl 'http://127.0.0.1:8000/helloworld/kratos'
{"message":"Hello kratos"}
3、开发一个aritcle示例
3.1、Protobuf 定义(api/hellworld/v1/demo.proto)
syntax = "proto3";
package helloworld.v1;
import "google/api/annotations.proto";
option go_package = "helloworld/api/helloworld/v1;v1";
option java_multiple_files = true;
option java_package = "dev.kratos.api.helloworld.v1";
option java_outer_classname = "HelloworldProtoV1";
service ArticleService {
rpc GetArticle(GetArticleRequest) returns (GetArticleReply) {
option (google.api.http) = {
get: "/v1/article/{id}"
};
}
}
message GetArticleRequest {
int64 id = 1;
}
message GetArticleReply {
int64 id = 1;
string title = 2;
string content = 3;
}
然后执行
# 生成以下文件(文件内容自动生成):
# - demo.pb.go : 消息结构体
# - demo_http.pb.go : HTTP 路由和 Handler 接口
# - demo_grpc.pb.go : gRPC 服务接口
make api
3.2、数据访问层对象定义
internal/data/article.go
package data
import (
"context"
"github.com/go-kratos/kratos/v2/log"
"helloworld/internal/biz"
)
type ArticleDO struct {
ID int64
Title string
Content string
}
type ArticleRepo struct {
data *Data
log *log.Helper
}
// 这个其实就是对数据库的操作,实现了ArticleRepo接口的实现
func NewArticleRepo(data *Data, logger log.Logger) biz.ArticleRepo {
return &ArticleRepo{
data: data,
log: log.NewHelper(logger),
}
}
func (r *ArticleRepo) GetArticle(ctx context.Context, id int64) (*biz.Article, error) {
var article ArticleDO
if err := r.data.db.WithContext(ctx).First(&article, id).Error; err != nil {
return nil, err
}
// 将数据库对象转换为业务对象
return &biz.Article{
ID: article.ID,
Title: article.Title,
Content: article.Content,
}, nil
}
internal/data/data.go
package data
import (
"gorm.io/gorm"
"helloworld/internal/conf"
"github.com/go-kratos/kratos/v2/log"
"github.com/google/wire"
"gorm.io/driver/mysql"
)
// ProviderSet is data providers. ProviderSet 中加入NewArticleRepo
var ProviderSet = wire.NewSet(NewData, NewGreeterRepo, NewArticleRepo)
// Data .
type Data struct {
db *gorm.DB
}
// NewData .
func NewData(c *conf.Data, logger log.Logger) (*Data, func(), error) {
db, err := gorm.Open(mysql.Open(c.Database.Source), &gorm.Config{})
if err != nil {
return nil, nil, err
}
// 自动迁移数据库表结构
db.AutoMigrate(&ArticleDO{})
return &Data{
db: db,
}, func() {
sqlDB, _ := db.DB()
sqlDB.Close()
}, nil
}
3.3、业务逻辑层
internal/biz/article.go
package biz
import (
"context"
"github.com/go-kratos/kratos/v2/log"
)
type Article struct {
ID int64
Title string
Content string
}
type ArticleRepo interface {
GetArticle(ctx context.Context, id int64) (*Article, error)
}
type ArticleUsecase struct {
repo ArticleRepo
log *log.Helper
}
func NewArticleUsecase(repo ArticleRepo, logger log.Logger) *ArticleUsecase {
return &ArticleUsecase{repo: repo, log: log.NewHelper(logger)}
}
func (uc *ArticleUsecase) GetArticle(ctx context.Context, id int64) (*Article, error) {
return uc.repo.GetArticle(ctx, id)
}
修改 internal/biz/biz.go,增加Provider
var ProviderSet = wire.NewSet(NewGreeterUsecase, NewArticleUsecase)
3.3、服务层
internal/service/article.go
package service
import (
"context"
pb "helloworld/api/helloworld/v1"
"helloworld/internal/biz"
)
type ArticleService struct {
pb.UnimplementedArticleServiceServer
uc *biz.ArticleUsecase
}
func NewArticleService(uc *biz.ArticleUsecase) *ArticleService {
return &ArticleService{uc: uc}
}
func (s *ArticleService) GetArticle(ctx context.Context, req *pb.GetArticleRequest) (*pb.GetArticleReply, error) {
article, err := s.uc.GetArticle(ctx, req.Id)
if err != nil {
return nil, err
}
return &pb.GetArticleReply{
Id: article.ID,
Title: article.Title,
Content: article.Content,
}, nil
}
修改 internal/service/service.go,增加Provider
var ProviderSet = wire.NewSet(NewGreeterService, NewArticleService)
3.4、修改server层
internal/server/http.go
package server
import (
"github.com/go-kratos/kratos/v2/log"
v1 "helloworld/api/helloworld/v1"
"helloworld/internal/conf"
"helloworld/internal/service"
"github.com/go-kratos/kratos/v2/transport/http"
)
// NewHTTPServer new an HTTP server.
func NewHTTPServer(
c *conf.Server,
greeterSvc *service.GreeterService,
articleSvc *service.ArticleService, // 新增参数
logger log.Logger,
) *http.Server {
svr := http.NewServer(http.Address(c.Http.Addr))
// 注册多个服务
v1.RegisterGreeterHTTPServer(svr, greeterSvc)
v1.RegisterArticleServiceHTTPServer(svr, articleSvc) // 新增注册
return svr
}
internal/server/grpc.go
package server
import (
v1 "helloworld/api/helloworld/v1"
"helloworld/internal/conf"
"helloworld/internal/service"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware/recovery"
"github.com/go-kratos/kratos/v2/transport/grpc"
)
// NewGRPCServer new a gRPC server.
func NewGRPCServer(c *conf.Server,
greeterSvc *service.GreeterService,
articleSvc *service.ArticleService, // 新增参数
logger log.Logger,
) *grpc.Server {
var opts = []grpc.ServerOption{
grpc.Middleware(
recovery.Recovery(),
),
}
if c.Grpc.Network != "" {
opts = append(opts, grpc.Network(c.Grpc.Network))
}
if c.Grpc.Addr != "" {
opts = append(opts, grpc.Address(c.Grpc.Addr))
}
if c.Grpc.Timeout != nil {
opts = append(opts, grpc.Timeout(c.Grpc.Timeout.AsDuration()))
}
srv := grpc.NewServer(opts...)
v1.RegisterGreeterServer(srv, greeterSvc)
v1.RegisterArticleServiceServer(srv, articleSvc)
return srv
}
3.5、重新生成代码
cd cmd/helloworld/ && wire gen
查看cmd/helloworld/wire_gen.go是否生成了
3.6、配置文件配置
configs/config.yaml
server:
http:
addr: 0.0.0.0:8000
timeout: 1s
grpc:
addr: 0.0.0.0:9000
timeout: 1s
data:
database:
driver: mysql
source: root:root@123@tcp(127.0.0.1:3306)/journey?parseTime=True&loc=Local
redis:
addr: 127.0.0.1:6379
read_timeout: 0.2s
write_timeout: 0.2s
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。