傳媒公司做網(wǎng)站條件百度關(guān)鍵詞推廣方案
該文章為學(xué)習(xí)開源微服務(wù)框架kratos的學(xué)習(xí)筆記!官方文檔見:簡介 | Kratos
Kratos 一套輕量級 Go 微服務(wù)框架,包含大量微服務(wù)相關(guān)框架及工具。
一、Kratos 項(xiàng)目結(jié)構(gòu)簡介
通過 Kratos 工具生成的?Go工程化項(xiàng)目模板如下:
application
|____api
| |____helloworld
| | |____v1
| | |____errors
|____cmd
| |____helloworld
|____configs
|____internal
| |____conf
| |____data
| |____biz
| |____service
| |____server
|____test
|____pkg
|____go.mod
|____go.sum
|____LICENSE
|____README.md
二、kratos 依賴注入關(guān)系圖
?其中有關(guān)依賴注入的詳細(xì)文檔見:Go工程化 - 依賴注入 | Kratos
以下是我自己總結(jié)的kratos依賴注入關(guān)系圖:
特別注意:data層的 NewXxxRepo 返回的是 biz 層定義的實(shí)體數(shù)倉的接口類型!!!
這樣做的目的:正常情況是 data 層定義好數(shù)據(jù)操作函數(shù)后被 biz 層調(diào)用,但這里是 biz 層定義好操作數(shù)據(jù)層的接口,然后讓 data 層去實(shí)現(xiàn),從而實(shí)現(xiàn) data 層對 biz 層的反向依賴。這樣做的好處是方便 data 層重構(gòu)(比如數(shù)據(jù)存儲由 mysql 改為 sqlServer 等),而不需要修改任何 biz 層的代碼。
//下面代碼位于 data/article.go
// 注意返回參數(shù)為 biz 層的接口,ArticleRepo 需要實(shí)現(xiàn) biz.ArticleRepo 接口
func NewArticleRepo(data *Data, logger log.Logger) biz.ArticleRepo {return &articleRepo{data: data,log: log.NewHelper(logger),}
}// 下面代碼位于 biz/article.go
// 在 biz 層定義好數(shù)據(jù)操作層(data層)的接口,以便讓 data 層實(shí)現(xiàn),不管 data 層今后如何實(shí)現(xiàn)或重構(gòu),都不影響 biz 層的業(yè)務(wù)代碼
type ArticleRepo interface {// dbListArticle(ctx context.Context) ([]*Article, error)GetArticle(ctx context.Context, id int64) (*Article, error)CreateArticle(ctx context.Context, article *Article) errorUpdateArticle(ctx context.Context, id int64, article *Article) errorDeleteArticle(ctx context.Context, id int64) error
}
三、依賴注入生成的代碼實(shí)例
運(yùn)用 google/wire 工具將上述依賴注入生成具體的kratos項(xiàng)目代碼示例:
原始 wire.go 代碼:
// initApp init kratos application.
func initApp(*conf.Server, *conf.Data, *conf.Auth, log.Logger) (*kratos.App, func(), error) {panic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, newApp))
}
?工具生成的代碼wire_gen.go:
// initApp init kratos application.
func initApp(confServer *conf.Server, confData *conf.Data, auth *conf.Auth, logger log.Logger) (*kratos.App, func(), error) {dataData, cleanup, err := data.NewData(confData, logger)if err != nil {return nil, nil, err}articleRepo := data.NewArticleRepo(dataData, logger)articleUsecase := biz.NewArticleUsecase(articleRepo, logger)blogService := service.NewBlogService(articleUsecase, logger)userRepo := data.NewUserRepo(dataData, logger)encryptService := biz.NewEncryptService(auth)accountUseCase := biz.NewAccountUseCase(logger, auth, userRepo, encryptService)accountService := service.NewAccountService(logger, accountUseCase)httpServer := server.NewHTTPServer(confServer, logger, blogService, accountService)grpcServer := server.NewGRPCServer(confServer, logger, blogService, accountService)app := newApp(logger, httpServer, grpcServer)return app, func() {cleanup()}, nil
}