Спрощення впровадження залежностей у Go за допомогою Wire — Частина 2.

Linkedin Github Wire Part -1

pic

Продовження…

[

Спрощення інжекції залежностей у Go за допомогою Wire.

Linkedin Github

medium.com

](/@rishusahu23/simplifying-dependency-injection-in-go-with-wire-21bd77997b2e?source=post_page-----5071f65de76f--------------------------------)

Досі наша подорож була захоплюючою. Ми досліджували, як інтегрувати DAO (Data Access Object) у сервіси та керувати їх залежностями без зусиль за допомогою Wire.

Тепер давайте розглянемо випадок використання, коли нам потрібно реалізувати Стратегічний патерн (Strategy Pattern) у нашому сервісі. Як ми будемо вирішувати його залежності? Звучить цікаво!

У цьому розділі ми розглянемо два ключових аспекти:

  1. Як використовувати Стратегічний патерн (Strategy Pattern).
  2. Як інжектувати залежності через Wire.

Я вважаю, що ми вже покрили це, тому давайте продовжимо з цього:

package user  

import (  
 "context"  
 "fmt"  
 "github.com/pkg/errors"  
 "github.com/rishu/microservice/external/post"  
 "github.com/rishu/microservice/gen/api/rpc"  
 userPb "github.com/rishu/microservice/gen/api/user"  
 customerrors "github.com/rishu/microservice/pkg/errors"  
 store "github.com/rishu/microservice/pkg/in_memory_store"  
 txn "github.com/rishu/microservice/pkg/transaction"  
 "github.com/rishu/microservice/user/dao"  
 "github.com/rishu/microservice/user/dao/mongo"  
)  

type Service struct {  
 dao dao.UserDao  
 txnManager txn.TransactionManager  
 userPb.UnimplementedUserServiceServer  
}  

func (s *Service) GetUser(ctx context.Context, req *userPb.GetUserRequest) (*userPb.GetUserResponse, error) {  
 user, err := s.dao.Get(ctx, mongo.WithUserId(req.GetUserId()))  
 fmt.Println(user)  
 if err != nil {  
 if errors.Is(err, customerrors.ErrRecordNotFound) {  
 return &userPb.GetUserResponse{  
 Status: rpc.StatusRecordNotFound(""),  
 }, nil  
 }  
 return &userPb.GetUserResponse{  
 Status: rpc.StatusInternal(""),  
 }, nil  
 }  
 return &userPb.GetUserResponse{  
 Status: rpc.StatusOk(),  
 User: user,  
 }, nil  
}  

func (s *Service) CreateUser(ctx context.Context, req *userPb.CreateUserRequest) (*userPb.CreateUserResponse, error) {  
 _, err := s.dao.Get(ctx, mongo.WithUserId(req.GetUser().GetId()))  
 if err != nil && !errors.Is(err, customerrors.ErrRecordNotFound) {  
 return &userPb.CreateUserResponse{  
 Status: rpc.StatusInternal(""),  
 }, nil  
 }  

 err = s.dao.Create(ctx, req.GetUser())  

 if err != nil {  
 return &userPb.CreateUserResponse{  
 Status: rpc.StatusInternal(""),  
 }, nil  
 }  
 return &userPb.CreateUserResponse{  
 Status: rpc.StatusOk(),  
 }, nil  
}  

func (s *Service) GetPost(ctx context.Context, req *userPb.GetPostRequest) (*userPb.GetPostResponse, error) {  
 return &userPb.GetPostResponse{  
 Status: rpc.StatusOk(),  
 }, nil  
}  

func NewService(dao dao.UserDao, txnManager txn.TransactionManager, postClient post.Client, redisInMemoryStore store.InMemoryStore) *Service {  
 return &Service{  
 dao: dao,  
 txnManager: txnManager,  
 }  
}  

var _ userPb.UserServiceServer = (*Service)(nil)

З наданого коду видно, що дані користувача отримуються безпосередньо з бази даних. Однак використання кешу стає важливим для покращення продуктивності в умовах високого навантаження та вимог до низької затримки.

Ми не можемо просто замінити базу даних на кеш. Натомість ми можемо застосувати Стратегічний патерн (Strategy Pattern), що дозволить нам отримувати дані або з бази даних, або з кешу в залежності від обраної реалізації. Для цього прикладу припустимо, що ми використовуємо або базу даних, або кеш, але не обидва.

Я вже інтегрував бібліотеку Redis та реалізував методи Get/Set у своїй кодовій базі.
You can review the code at the following link:-**

[

redis · rishusahu23/microservice@afadc2d

Contribute to rishusahu23/microservice development by creating an account on GitHub.

github.com

](https://github.com/rishusahu23/microservice/commit/afadc2db7b47aabe92aa6930bc6079e386e3800b?source=post_page-----5071f65de76f--------------------------------)

Структура файлів для Стратегічного патерну (Strategy Pattern):-

user/  
├── dao/  
├── getuserstrategy/  
 ├── cache/  
 │ └── cache.go  
 ├── db/  
 │ └── db.go  
 ├── factory.go  
 └── strategy.go

Реалізація Стратегічного патерну для отримання користувачів:

Давайте побудуємо стратегію для отримання даних з бази даних спочатку:-

factory.go:-

package strategy  

import (  
 "context"  
 "fmt"  
 "github.com/google/wire"  
)  

type GetUserStrategyFactory interface {  
 GetStrategy(ctx context.Context, strategyType string) (GetUserStrategy, error)  
}  

type GetUserStrategyFactoryImpl struct {  
 dbStrategy GetUserStrategy  
}  

var (  
 FactoryWireSet = wire.NewSet(NewGetUserStrategyFactoryImpl, wire.Bind(new(GetUserStrategyFactory), new(*GetUserStrategyFactoryImpl)))  
)  

func NewGetUserStrategyFactoryImpl(dbStrategy GetUserStrategy) *GetUserStrategyFactoryImpl {  
 return &GetUserStrategyFactoryImpl{dbStrategy: dbStrategy}  

}  

func (g *GetUserStrategyFactoryImpl) GetStrategy(ctx context.Context, strategyType string) (GetUserStrategy, error) {  
 switch strategyType {  
 case "db":  
 return g.dbStrategy, nil  
 default:  
 return nil, fmt.Errorf("no such strategy exist %v", strategyType)  
 }  
}
var (  
 FactoryWireSet = wire.NewSet(NewGetUserStrategyFactoryImpl, wire.Bind(new(GetUserStrategyFactory), new(*GetUserStrategyFactoryImpl)))  
)

strategy.go:-

package strategy  

import (  
 "context"  
 "github.com/rishu/microservice/gen/api/user"  
)  

type GetUserStrategy interface {  
 GetUser(ctx context.Context, request *GetUserRequest) (*GetUserResponse, error)  
}  

type GetUserRequest struct {  
 UserId string  
}  

type GetUserResponse struct {  
 User *user.User  
}

db.go:-

package db  

import (  
 "context"  
 "github.com/google/wire"  
 "github.com/rishu/microservice/user/dao"  
 "github.com/rishu/microservice/user/dao/mongo"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
)  

type DB struct {  
 dao dao.UserDao  
}  

func NewDB(dao dao.UserDao) *DB {  
 return &DB{dao: dao}  
}  

var (  
 GetUserDBWireSet = wire.NewSet(NewDB, wire.Bind(new(strategy.GetUserStrategy), new(*DB)))  
)  

func (d *DB) GetUser(ctx context.Context, req *strategy.GetUserRequest) (*strategy.GetUserResponse, error) {  
 user, err := d.dao.Get(ctx, mongo.WithUserId(req.UserId))  
 if err != nil {  
 return nil, err  
 }  
 return &strategy.GetUserResponse{  
 User: user,  
 }, nil  
}

service.go:- Змініть файл service.go, додавши нижченаведений фрагмент:

package user  

import (  
 "context"  
 "github.com/pkg/errors"  
 "github.com/rishu/microservice/gen/api/rpc"  
 userPb "github.com/rishu/microservice/gen/api/user"  
 customerrors "github.com/rishu/microservice/pkg/errors"  
 txn "github.com/rishu/microservice/pkg/transaction"  
 "github.com/rishu/microservice/user/dao"  
 "github.com/rishu/microservice/user/dao/mongo"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
)  

type Service struct {  
 dao dao.UserDao  
 txnManager txn.TransactionManager  
 userPb.UnimplementedUserServiceServer  
 factory strategy.GetUserStrategyFactory  
}  

func NewService(dao dao.UserDao, txnManager txn.TransactionManager, factory strategy.GetUserStrategyFactory) *Service {  
 return &Service{  
 dao: dao,  
 txnManager: txnManager,  
 factory: factory,  
 }  
}  

func (s *Service) GetUser(ctx context.Context, req *userPb.GetUserRequest) (*userPb.GetUserResponse, error) {  
 strategyImpl, err := s.factory.GetStrategy(ctx, "db")  
 if err != nil {  
 return &userPb.GetUserResponse{
Status: rpc.StatusInternal(err.Error()),  
 }, nil  
 }  
 resp, err := strategyImpl.GetUser(ctx, &strategy.GetUserRequest{  
 UserId: req.GetUserId(),  
 })  
 if err != nil {  
 return &userPb.GetUserResponse{  
 Status: rpc.StatusInternal(err.Error()),  
 }, nil  
 }  
 return &userPb.GetUserResponse{  
 Status: rpc.StatusOk(),  
 User: resp.User,  
 }, nil  
}  

func (s *Service) CreateUser(ctx context.Context, req *userPb.CreateUserRequest) (*userPb.CreateUserResponse, error) {  
 _, err := s.dao.Get(ctx, mongo.WithUserId(req.GetUser().GetId()))  
 if err != nil && !errors.Is(err, customerrors.ErrRecordNotFound) {  
 return &userPb.CreateUserResponse{  
 Status: rpc.StatusInternal(""),  
 }, nil  
 }  

 err = s.dao.Create(ctx, req.GetUser())  

 if err != nil {  
 return &userPb.CreateUserResponse{  
 Status: rpc.StatusInternal(""),  
 }, nil  
 }  
 return &userPb.CreateUserResponse{  
 Status: rpc.StatusOk(),  
 }, nil  
}  

func (s *Service) GetPost(ctx context.Context, req *userPb.GetPostRequest) (*userPb.GetPostResponse, error) {  
 return &userPb.GetPostResponse{  
 Status: rpc.StatusOk(),  
 }, nil  
}  

var _ userPb.UserServiceServer = (*Service)(nil)

Тепер запустимо wire:-

wire ./user/wire

ми отримаємо наступну помилку.
Ми можемо дебажити, чому виникла помилка?

wire: /Users/rishusahu/go/src/github.com/rishu/microservice/user/wire/wire.go:33:1: inject InitialiseUserService: no provider found for github.com/rishu/microservice/user/getuserstrategy.GetUserStrategyFactory  
 needed by *github.com/rishu/microservice/user.Service in provider "NewService" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/service.go:22:6)  
wire: github.com/rishu/microservice/user/wire: generate failed  
wire: at least one generate failure

Так, ви праві, ми не впровадили залежність GetUserStrategyFactory у wire. Оновіть wire, додавши наступний фрагмент коду.

wire.go:-

//go:build wireinject  
// +build wireinject  

package wire  

import (  
 "crypto/tls"  
 "github.com/google/wire"  
 "github.com/rishu/microservice/config"  
 "github.com/rishu/microservice/external/post"  
 mongo2 "github.com/rishu/microservice/pkg/transaction/mongo"  
 "github.com/rishu/microservice/user"  
 mongoDao "github.com/rishu/microservice/user/dao/mongo"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
 "go.mongodb.org/mongo-driver/mongo"  
 "net/http"  
)  

func GetPostClientProvider(provider *post.ClientImpl) post.Client {  
 return provider  
}  

func InitialiseUserService(conf *config.Config, mongoClient *mongo.Client) *user.Service {  
 wire.Build(  
 user.NewService,  
 mongoDao.UserDaoWireSet,  
 mongo2.DefaultTxnManagerWireSet,  
 strategy.FactoryWireSet,  
 )  
 return &user.Service{}  
}

Тепер знову запустіть wire. Це призведе до наступної помилки.

wire: /Users/rishusahu/go/src/github.com/rishu/microservice/user/wire/wire.go:31:1: inject InitialiseUserService: no provider found for github.com/rishu/microservice/user/getuserstrategy.GetUserStrategy  
 needed by *github.com/rishu/microservice/user/getuserstrategy.GetUserStrategyFactoryImpl in provider set "FactoryWireSet" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/getuserstrategy/factory.go:19:19)  
 needed by github.com/rishu/microservice/user/getuserstrategy.GetUserStrategyFactory in provider set "FactoryWireSet" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/getuserstrategy/factory.go:19:19)  
 needed by *github.com/rishu/microservice/user.Service in provider "NewService" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/service.go:22:6)  
wire: github.com/rishu/microservice/user/wire: generate failed  
wire: at least one generate failure

Чому? 😵‍💫

Оскільки GetUserStrategy потрібна кількома компонентами в FactoryWireSet (такими як GetUserStrategyFactoryImpl і GetUserStrategyFactory у factory.go), нам потрібно впровадити правильну реалізацію GetUserStrategy. Оновіть wire, додавши наступний фрагмент коду, щоб виправити помилку.

wire.go:-

//go:build wireinject  
// +build wireinject  

package wire  

import (  
 "crypto/tls"  
 "github.com/google/wire"  
 "github.com/rishu/microservice/config"  
 "github.com/rishu/microservice/external/post"  
 mongo2 "github.com/rishu/microservice/pkg/transaction/mongo"  
 "github.com/rishu/microservice/user"  
 mongoDao "github.com/rishu/microservice/user/dao/mongo"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
 "github.com/rishu/microservice/user/getuserstrategy/db"  
 "go.mongodb.org/mongo-driver/mongo"  
 "net/http"  
)  

func GetPostClientProvider(provider *post.ClientImpl) post.Client {  
 return provider  
}  

func InitialiseUserService(conf *config.Config, mongoClient *mongo.Client) *user.Service {  
 wire.Build(  
 user.NewService,  
 mongoDao.UserDaoWireSet,  
 mongo2.DefaultTxnManagerWireSet,  
 strategy.FactoryWireSet,  
 db.GetUserDBWireSet,  
 )  
 return &user.Service{}  
}

wire ./user/wire

Тепер має працювати. 😎

Ми можемо звернутися до цього файлу wire_gen.go, щоб зрозуміти, як реалізовано впровадження залежностей.
```
// Code generated by Wire. DO NOT EDIT.
//go:generate wire
//go:build !wireinject
// +build !wireinject

package wire

import (
"crypto/tls"
"github.com/rishu/microservice/config"
"github.com/rishu/microservice/external/post"
mongo3 "github.com/rishu/microservice/pkg/transaction/mongo"
"github.com/rishu/microservice/user"
mongo2 "github.com/rishu/microservice/user/dao/mongo"
"github.com/rishu/microservice/user/getuserstrategy"
"github.com/rishu/microservice/user/getuserstrategy/db"
"go.mongodb.org/mongo-driver/mongo"
"net/http"
)

// Впровадження з wire.go:

func InitialiseUserService(conf *config.Config, mongoClient *mongo.Client) *user.Service {
userDaoMongo := mongo2.NewUserDaoMongo(mongoClient, conf)
mongoTransactionManager := mongo3.NewMongoTransactionManager(mongoClient)
dbDB := db.NewDB(userDaoMongo)
getUserStrategyFactoryImpl := strategy.NewGetUserStrategyFactoryImpl(dbDB)
service := user.NewService(userDaoMongo, mongoTransactionManager, getUserStrategyFactoryImpl)
return service
}

// wire.go:

func GetPostClientProvider(provider *post.ClientImpl) post.Client {
return provider
}
```

Давайте реалізуємо отримання з кешу також:

factory.go:-

package strategy  

import (  
 "context"  
 "fmt"  
 "github.com/google/wire"  
)  

type GetUserStrategyFactory interface {  
 GetStrategy(ctx context.Context, strategyType string) (GetUserStrategy, error)  
}  

type GetUserStrategyFactoryImpl struct {  
 dbStrategy GetUserStrategy  
 cacheStrategy GetUserStrategy  
}  

var (  
 FactoryWireSet = wire.NewSet(NewGetUserStrategyFactoryImpl, wire.Bind(new(GetUserStrategyFactory), new(*GetUserStrategyFactoryImpl)))  
)  

func NewGetUserStrategyFactoryImpl(dbStrategy GetUserStrategy, cacheStrategy GetUserStrategy) *GetUserStrategyFactoryImpl {  
 return &GetUserStrategyFactoryImpl{dbStrategy: dbStrategy,  
 cacheStrategy: cacheStrategy,  
 }  
}  

func (g *GetUserStrategyFactoryImpl) GetStrategy(ctx context.Context, strategyType string) (GetUserStrategy, error) {  
 switch strategyType {  
 case "db":  
 return g.dbStrategy, nil  
 case "cache":  
 return g.cacheStrategy, nil  
 default:  
 return nil, fmt.Errorf("такої стратегії не існує: %v", strategyType)  
 }  
}

cache.go:-

package cache  

import (  
 "context"  
 "fmt"  
 "github.com/google/wire"  
 userPb "github.com/rishu/microservice/gen/api/user"  
 store "github.com/rishu/microservice/pkg/in_memory_store"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
 "google.golang.org/protobuf/encoding/protojson"  
)  

type Cache struct {  
 redisInMemoryStore store.InMemoryStore  
}  

func NewCache(redisInMemoryStore store.InMemoryStore) *Cache {  
 return &Cache{redisInMemoryStore: redisInMemoryStore}  
}  

var (  
 GetUserCacheWireSet = wire.NewSet(NewCache, wire.Bind(new(strategy.GetUserStrategy), new(*Cache)))  
)  

func getKey(userId string) string {  
 return fmt.Sprintf("%v", userId)  
}  
func (c *Cache) GetUser(ctx context.Context, request *strategy.GetUserRequest) (*strategy.GetUserResponse, error) {  
 userStr, err := c.redisInMemoryStore.Get(ctx, getKey(request.UserId))  
 if err != nil {  
 return nil, err  
 }  
 user := &userPb.User{}  
 err = protojson.Unmarshal([]byte(userStr), user)  
 if err != nil {  
 return nil, err  
 }  
 return &strategy.GetUserResponse{  
 User: user,  
 }, nil  
}

wire.go:-

//go:build wireinject  
// +build wireinject  

package wire  

import (  
 "crypto/tls"  
 "github.com/google/wire"  
 "github.com/rishu/microservice/config"  
 "github.com/rishu/microservice/external/post"  
 mongo2 "github.com/rishu/microservice/pkg/transaction/mongo"  
 "github.com/rishu/microservice/user"  
 mongoDao "github.com/rishu/microservice/user/dao/mongo"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
 "github.com/rishu/microservice/user/getuserstrategy/cache"
)  

"github.com/rishu/microservice/user/getuserstrategy/db"  
 "go.mongodb.org/mongo-driver/mongo"  
 "net/http"  
)  

func GetPostClientProvider(provider *post.ClientImpl) post.Client {  
 return provider  
}  

func InitialiseUserService(conf *config.Config, mongoClient *mongo.Client) *user.Service {  
 wire.Build(  
 user.NewService,  
 mongoDao.UserDaoWireSet,  
 mongo2.DefaultTxnManagerWireSet,  
 strategy.FactoryWireSet,  
 db.GetUserDBWireSet,  
 cache.GetUserCacheWireSet,  
 )  
 return &user.Service{}  
}

Нічого складного, правда? Якщо ми запустимо wire, то це повинно працювати.
🤔

wire ./user/wire

wire: /Users/rishusahu/go/src/github.com/rishu/microservice/user/getuserstrategy/factory.go:22:6: provider has multiple parameters of type github.com/rishu/microservice/user/getuserstrategy.GetUserStrategy  
wire: github.com/rishu/microservice/user/wire: generate failed  
wire: at least one generate failure

pic

Ні, це не спрацювало! Давайте розберемося, чому і виправимо це.

Ось що відбувається простими словами:

  1. У нас є структура GetUserStrategyFactoryImpl, яка має два поля (dbStrategy і cacheStrategy), обидва типу GetUserStrategy.
  2. Коли ми використовуємо wire, він намагається згенерувати код для інжекції залежностей. Однак, wire плутається, оскільки є два параметри одного типу (GetUserStrategy), і він не знає, як їх вирішити.

Як це виправити:-

  1. Давайте додамо файли db.go і cache.go в пакет getuserstrategy. Це зроблено для того, щоб уникнути циклічних залежностей. Також можуть бути інші способи усунення циклічних залежностей.
  2. Змінімо factory.go, щоб використовувати конкретні реалізації замість інтерфейсів.
package strategy  

import (  
 "context"  
 "fmt"  
 "github.com/google/wire"  
)  

type GetUserStrategyFactory interface {  
 GetStrategy(ctx context.Context, strategyType string) (GetUserStrategy, error)  
}  

type GetUserStrategyFactoryImpl struct {  
 dbStrategy *DB  
 cacheStrategy *Cache  
}  

var (  
 FactoryWireSet = wire.NewSet(NewGetUserStrategyFactoryImpl, wire.Bind(new(GetUserStrategyFactory), new(*GetUserStrategyFactoryImpl)))  
)  

func NewGetUserStrategyFactoryImpl(dbStrategy *DB, cacheStrategy *Cache) *GetUserStrategyFactoryImpl {  
 return &GetUserStrategyFactoryImpl{dbStrategy: dbStrategy,  
 cacheStrategy: cacheStrategy,  
 }  
}  

func (g *GetUserStrategyFactoryImpl) GetStrategy(ctx context.Context, strategyType string) (GetUserStrategy, error) {  
 switch strategyType {  
 case "db":  
 return g.dbStrategy, nil  
 case "cache":  
 return g.cacheStrategy, nil  
 default:  
 return nil, fmt.Errorf("no such strategy exist %v", strategyType)  
 }  
}

Тепер, NewGetUserStrategyFactoryImpl приймає конкретні реалізації замість абстракцій, і DB та Cache мають різні типи.

  1. Змінімо wire.go
 //go:build wireinject  
 // +build wireinject  

 package wire  

 import (  
 "crypto/tls"  
 "github.com/google/wire"  
 "github.com/rishu/microservice/config"  
 "github.com/rishu/microservice/external/post"  
 mongo2 "github.com/rishu/microservice/pkg/transaction/mongo"  
 "github.com/rishu/microservice/user"  
 mongoDao "github.com/rishu/microservice/user/dao/mongo"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
 "go.mongodb.org/mongo-driver/mongo"  
 "net/http"  
 )  

 func GetPostClientProvider(provider *post.ClientImpl) post.Client {  
 return provider  
 }  

 func InitialiseUserService(conf *config.Config, mongoClient *mongo.Client) *user.Service {  
 wire.Build(  
 user.NewService,  
 mongoDao.UserDaoWireSet,  
 mongo2.DefaultTxnManagerWireSet,  
 strategy.FactoryWireSet,  
 strategy.NewDB,  
 strategy.NewCache,  
 )  
 return &user.Service{}  
 }

Тут ми замінили GetUserDBWireSet на NewDB, оскільки NewGetUserStrategyFactoryImpl потребує конкретний тип *DB, який повертається з NewDB, і те саме для NewCache.

4.
Знову команда wire.

wire ./user/wire

Ми отримаємо таку помилку.

wire: /Users/rishusahu/go/src/github.com/rishu/microservice/user/wire/wire.go:31:1: inject InitialiseUserService: no provider found for github.com/rishu/microservice/pkg/in_memory_store.InMemoryStore  
 needed by *github.com/rishu/microservice/user/getuserstrategy.Cache in provider "NewCache" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/getuserstrategy/cache.go:16:6)  
 needed by *github.com/rishu/microservice/user/getuserstrategy.GetUserStrategyFactoryImpl in provider set "FactoryWireSet" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/getuserstrategy/factory.go:19:19)  
 needed by github.com/rishu/microservice/user/getuserstrategy.GetUserStrategyFactory in provider set "FactoryWireSet" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/getuserstrategy/factory.go:19:19)  
 needed by *github.com/rishu/microservice/user.Service in provider "NewService" (/Users/rishusahu/go/src/github.com/rishu/microservice/user/service.go:22:6)  
wire: github.com/rishu/microservice/user/wire: generate failed  
wire: at least one generate failure

Це вказує на те, що ми використовуємо store.InMemoryStore для Redis. Тому нам потрібно інжектувати його залежність. Для цього ми скористаємося RedisWireSet, а також store.InMemoryStore внутрішньо використовує redisClient, тому потрібно додати redisClient *redisV9.Client до конфігурації Wire.

wire.go:-

 //go:build wireinject  
 // +build wireinject  

 package wire  

 import (  
 "crypto/tls"  
 "github.com/google/wire"  
 redisV9 "github.com/redis/go-redis/v9"  
 "github.com/rishu/microservice/config"  
 "github.com/rishu/microservice/external/post"  
 "github.com/rishu/microservice/pkg/in_memory_store/redis"  
 mongo2 "github.com/rishu/microservice/pkg/transaction/mongo"  
 "github.com/rishu/microservice/user"  
 mongoDao "github.com/rishu/microservice/user/dao/mongo"  
 strategy "github.com/rishu/microservice/user/getuserstrategy"  
 "go.mongodb.org/mongo-driver/mongo"  
 "net/http"  
 )  

 func GetPostClientProvider(provider *post.ClientImpl) post.Client {  
 return provider  
 }  

 func InitialiseUserService(conf *config.Config, mongoClient *mongo.Client, redisClient *redisV9.Client) *user.Service {  
 wire.Build(  
 user.NewService,  
 mongoDao.UserDaoWireSet,  
 mongo2.DefaultTxnManagerWireSet,  
 strategy.FactoryWireSet,  
 strategy.NewDB,  
 strategy.NewCache,  
 redis.RedisWireSet,  
 )  
 return &user.Service{}  
 }
  1. Знову команда wire. Тепер все повинно працювати.

wire ./user/wire

pic

  1. Оскільки ми використали redisClient, потрібно налаштувати сервер Redis. Я вже поділився посиланням на репозиторій для налаштування Redis.

  2. Передайте redisClient з main.go

redisClient := redis2.GetRedisClient(conf)  
 userPb.RegisterUserServiceServer(s, wire.InitialiseUserService(conf, mongoClient,redisClient))
  1. Перезапустіть сервер, і він буде готовий до тестування.

Перевірте мій репозиторій для повного коду.

[

GitHub - rishusahu23/microservice

Contribute to rishusahu23/microservice development by creating an account on GitHub.

github.com

](https://github.com/rishusahu23/microservice?source=post_page-----5071f65de76f--------------------------------)

Дякую за увагу!!

Перекладено з: Simplifying Dependency Injection in Go with Wire —2nd Part.

Leave a Reply

Your email address will not be published. Required fields are marked *