go语言使用kratos框架,使用工厂模式创建对象时,biz层和data层出现循环依赖的错误解决方案

1 篇文章 0 订阅

仅自己想的一个解决方法,如有不妥之处,还望大家不吝赐教,及时纠正我。

正文开始:

工厂方式创建对象,无非是想根据不同的参数获取到创建的不同对象。

先抛一个结论,kratos框架中,data(包)层会依赖于biz(包)层。

下面这段伪代码方法是写在biz包的一个UseCase.go中,而NewIosP8(xx,xx)是属于data包的xxx,所以在此处就有了biz包依赖data包,在结合上面的结论。

func (cuc *CertificateUseCase) GetCerInter(Type string) CertificateRepo {
	switch Type {
	case constant.IOS_P8:
		return data.NewIosP8(xx,xx);
	default:
		return nil
	}
}

问题:go中不允许不同的包相互依赖,因此编译启动项目时会报循环依赖的错误。

解决:kratos中使用了wire的编译时依赖注入,将UseCase.go中所有这个方法可能创建出来的对象都提前创建出来,并关联到这个CertificateUseCase下,如下图:

func wireApp(confServer *conf.Server, confData *conf.Data, logger log.Logger) (*kratos.App, func(), error) {
	dataData, err := data.NewData(confData, logger)
	if err != nil {
		return nil, nil, err
	}
	parentCertificateRepo := data.NewParentCertificateRepo(dataData, logger)
	iosP8CertificateRepo := data.NewIosP8Certificate(dataData)
	iosPCertificateRepo := data.NewIosPCertificate(dataData)
	andHuaweiCertificateRepo := data.NewAndHuaweiCertificate(dataData)
	andMeizuCertificateRepo := data.NewAndMeizuCertificate(dataData)
	miAndGoogleRepo := data.NewMiAndGoogle(dataData)
	andOppoCertificateRepo := data.NewAndOppoCertificate(dataData)
	andVivoCertificateRepo := data.NewAndVivoCertificate(dataData)
	certificateUseCase := biz.NewCertificateUseCase(parentCertificateRepo, andHuaweiCertificateRepo, iosPCertificateRepo, iosP8CertificateRepo, andMeizuCertificateRepo, miAndGoogleRepo, andOppoCertificateRepo, andVivoCertificateRepo, logger)
	certificateService := service.NewCertificateService(certificateUseCase)
	grpcServer := server.NewGRPCServer(confServer, appService, certificateService, imUserStaticService, userService, clientAppService, logger)
	app := newApp(logger, grpcServer)
	return app, func() {
		//cleanup()
	}, nil
}

创建certificateUseCase的时候将前面创建好的xxxRepo都关联进去。后面的工厂方法就不需要再调用data包下的创建逻辑了,直接获取即可,如下图:

func (cuc *CertificateUseCase) GetCerInter(Type string) CertificateRepo {
	switch Type {
	case constant.IOS_P8:
		return cuc.iosP8
	case constant.IOS_P12, constant.IOS_Push_Kit:
		return cuc.ios
	case constant.MI, constant.Google:
		return cuc.miAndGoogle
	case constant.HuaWei:
		return cuc.huawei
	case constant.MeiZu:
		return cuc.meizu
	case constant.VivoAnd:
		return cuc.vivo
	case constant.OppoAnd:
		return cuc.oppo
	default:
		return nil
	}
}

我们只需要将已经创建好的对象根据传入的不同Type值直接返回即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!根据您的描述,您希望在现有的Kratos + Ent + Redis框架中实现登录功能,并生成动态验证码。以下是一个简单的实现示例: 首先,安装必要的依赖包: ```shell go get github.com/go-kratos/kratos go get github.com/go-kratos/ent go get github.com/go-redis/redis/v8 go get github.com/gin-gonic/gin ``` 然后,创建一个名为`main.go`的文件,并添加以下代码: ```go package main import ( "context" "fmt" "math/rand" "net/http" "strconv" "time" "github.com/go-kratos/ent/entc" "github.com/go-kratos/ent/entc/sql" "github.com/go-kratos/ent/examples/ent_user" "github.com/go-redis/redis/v8" "github.com/gin-gonic/gin" ) func main() { // 初始化数据库连接 client, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/ent_demo") if err != nil { fmt.Printf("failed opening connection to mysql: %v", err) return } defer client.Close() // 初始化Redis连接 redisClient := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", DB: 0, }) // 初始化Kratos服务 router := gin.Default() // 登录接口 router.POST("/login", func(c *gin.Context) { // 获取用户输入的手机号和密码 phone := c.PostForm("phone") password := c.PostForm("password") // 从数据库中查询用户信息 user, err := client.User.Query().Where(ent_user.Phone(phone)).Only(context.Background()) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "用户不存在"}) return } // 验证密码是否正确 if user.Password != password { c.JSON(http.StatusBadRequest, gin.H{"error": "密码错误"}) return } // 生成动态验证码 code := generateCode() // 将验证码存储到Redis中,设置有效期为5分钟 err = redisClient.Set(context.Background(), phone, code, 5*time.Minute).Err() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "验证码生成失败"}) return } // 发送验证码到用户手机(这里省略具体的发送逻辑) c.JSON(http.StatusOK, gin.H{"message": "验证码已发送,请输入验证码进行登录"}) }) // 验证码登录接口 router.POST("/login/verify", func(c *gin.Context) { // 获取用户输入的手机号和验证码 phone := c.PostForm("phone") code := c.PostForm("code") // 从Redis中获取验证码 storedCode, err := redisClient.Get(context.Background(), phone).Result() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "验证码已过期"}) return } // 验证验证码是否匹配 if code != storedCode { c.JSON(http.StatusBadRequest, gin.H{"error": "验证码错误"}) return } // TODO: 验证通过,进行登录操作 c.JSON(http.StatusOK, gin.H{"message": "登录成功"}) }) // 启动服务 router.Run(":8080") } // 生成6位随机数字验证码 func generateCode() string { rand.Seed(time.Now().UnixNano()) return strconv.Itoa(rand.Intn(900000) + 100000) } ``` 请确保您已正确配置数据库和Redis连接,并根据您的实际需求进行相应的修改。以上示例代码仅供参考,具体实现可能需要根据您的业务逻辑进行调整。祝您成功实现登录生成动态验证码功能!如果您有任何问题,请随提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值