golang beego结合wire依赖注入及自动路由

1 安装wire

1.1 通过命令直接安装

go install github.com/google/wire/cmd/wire@latest

1.2 通过go get方式安装

go get github.com/google/wire/cmd/wire

进入目录编译

cd C:\Users\leell\go\pkg\mod\github.com\google\wire@v0.6.0\cmd\wire
go build

然后将wire.exe移动到 C:\Users\leell\go\bin目录下

具体目录通过go env进行查看

C:\Users\leell\go>go env
set GO111MODULE=on
set GOARCH=amd64
set GOBIN=C:\Users\leell\go\bin

2 配置业务代码

我没有按照beego的默认目录,而是通过自定义app包名进行业务模块化

2.1 分类模块

app/category/category_controller.go

type Controller struct {controller.BaseControllerservice *Service
}func NewController(service *Service) *Controller {return &Controller{service: service}
}

app/category/category_service.go

type Service struct {dao *Dao
}func NewService(dao *Dao) *Service {return &Service{dao}
}

app/category/category_dao.go 

type Dao struct {ormer orm.Ormer
}func NewDao(ormer orm.Ormer) *Dao {return &Dao{ormer}
}

app/category/fx.go

package categoryimport ("github.com/beego/beego/v2/server/web""github.com/google/wire"
)type FxRouter struct {controller *Controller
}func NewAppRouter(controller *Controller) *FxRouter {return &FxRouter{controller}
}
func (r *FxRouter) Router(namespace *web.Namespace) {namespace.Get("/category", r.controller.GetAll)namespace.Get("/category/:id", r.controller.GetOne)namespace.Post("/category", r.controller.Post)namespace.Put("/category/:id", r.controller.Put)namespace.Delete("/category/:id", r.controller.Delete)
}var Set = wire.NewSet(NewController, NewService, NewDao, NewAppRouter)

app/fx.go:将分类模块引入app/fx.go中并且等待注册路由

package appimport ("github.com/beego/beego/v2/server/web""github.com/google/wire""zhiqu/app/category""zhiqu/app/login""zhiqu/app/user"
)type FxRouter struct {categoryFxRouter *category.FxRouterloginFxRouter    *login.FxRouteruserFxRouter     *user.FxRouter
}func NewAppRouter(categoryFxRouter *category.FxRouter,loginFxRouter *login.FxRouter,userFxRouter *user.FxRouter) *FxRouter {return &FxRouter{categoryFxRouter, loginFxRouter, userFxRouter}
}
func (r *FxRouter) Router(namespace *web.Namespace) {r.categoryFxRouter.Router(namespace)r.loginFxRouter.Router(namespace)r.userFxRouter.Router(namespace)
}var Set = wire.NewSet(NewAppRouter, category.Set, login.Set, user.Set)

2.2 项目wire定义总提供者provider

infrastructure/database/pgsql/db.go

package pgsqlimport ("fmt""github.com/beego/beego/v2/client/orm"beego "github.com/beego/beego/v2/server/web"_ "github.com/lib/pq"
)func init() {pgsqlUser, _ := beego.AppConfig.String("pgsqlUser")pgsqlPass, _ := beego.AppConfig.String("pgsqlPass")pgsqlDbName, _ := beego.AppConfig.String("pgsqlDbName")pgsqlHost, _ := beego.AppConfig.String("pgsqlHost")pgsqlPort, _ := beego.AppConfig.String("pgsqlPort")pgsqlSslMode, _ := beego.AppConfig.String("pgsqlSslMode")// 注册驱动err := orm.RegisterDriver("postgres", orm.DRPostgres)if err != nil {panic(err)}// 设置默认数据库err = orm.RegisterDataBase("default", "postgres", fmt.Sprintf("user=%s password=%s dbname=%s host=%s port=%s sslmode=%s", pgsqlUser, pgsqlPass, pgsqlDbName, pgsqlHost, pgsqlPort, pgsqlSslMode))if err != nil {panic(err)}
}
func NewPgsqlOrm() orm.Ormer {ormer := orm.NewOrm()return ormer
}

provider/provider.go

var Set = wire.NewSet(NewBeanFactory, pgsql.NewPgsqlOrm, app.Set)

2.3 给项目一个bean工厂

这点有点像spring的beanfactory,这里主要是:

(1)解决beego路由一开始执行init能够得到所有controller的实例

(2)go项目中存在recycle的循环依赖,这里就可以用beanFactory做一个中间过度

package providerimport ("github.com/beego/beego/v2/core/logs""sync""zhiqu/app"
)var (AppBeanFactory *BeanFactoryonce           sync.OnceBeeLog         *logs.BeeLogger
)type BeanFactory struct {AppFxRouter *app.FxRouter
}func init() {BeeLog = logs.NewLogger()err := BeeLog.SetLogger(logs.AdapterConsole)if err != nil {return}
}
func NewBeanFactory(appFxRouter *app.FxRouter) *BeanFactory {once.Do(func() {AppBeanFactory = &BeanFactory{AppFxRouter: appFxRouter,}})return AppBeanFactory
}

3 wire配置代码及生成gen代码

 wire/wire.go

//go:build wireinject
// +build wireinjectpackage wireimport ("zhiqu/provider"
)
import "github.com/google/wire"// wire.go 初始化模块
func NewApp() (*provider.BeanFactory, error) {panic(wire.Build(provider.Set))
}

执行wire命令生成gen代码得到wire/wire_gen.go

wire gen wire/wire.go

生成最终代码文件内容

wire/wire_gen.go

// Code generated by Wire. DO NOT EDIT.//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinjectpackage wireimport ("zhiqu/app/category""zhiqu/provider"
)// Injectors from wire.go:// wire.go 初始化模块
func NewApp() (*provider.BeanFactory, error) {categoryDao := category.NewDao()categoryService := category.NewService(categoryDao)categoryController := category.NewController(categoryService)beanFactory := provider.NewBeanFactory(categoryController)return beanFactory, nil
}

4 路由配置

routers/router.go

// Package routers 路由配置
package routersimport ("github.com/beego/beego/v2/server/web""zhiqu/wire"
)func init() {beanFactory, err := wire.NewApp()if err != nil {panic(err)}//这是一种可实现的依赖注入全自动方式ns := web.NewNamespace("/v1", func(namespace *web.Namespace) {beanFactory.AppFxRouter.Router(namespace)})web.SetStaticPath("/swagger", "swagger")web.AddNamespace(ns)
}

可以看出在路由文件中添加了wire生成的gen代码的获取的beanfactory工厂,然后将所有的单例go对象交由wire进行管理

注意:这里采用的是beego的web方式而不是beego方式,这里都是手动配置路由,不要去通过命令生成commentsRouter.go这样的路由文件

为啥不采用beego注册路由?

因为我们要想做到依赖注入,得确保controller、service、dao这些是单例,而beego注册的路由内部是现实每次收到请求都会通过反射技术重新构建一个controler进行处理。

正式因为最开始通过官方生成的项目配置路由注册时beego方式,而不能实现依赖注入,最终选择了gin+gorm+go.uber.org/fx的架构组合

5 查看最终结果

不过我不太推荐这种方式的依赖注入,虽然是在编译期实现了代码的生成,减少了启动通过反射来进行依赖注入的方式的时间,但是对开发人员来说多了一道工序。并且启动时间也要不了多久,而且编译器和运行期的依赖注入对接口运行是没有影响。

给大家推荐一块依赖注入框架:go.uber.org/fx

源代码:GitHub - leellun/beego-wire

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/316304.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

万兆以太网MAC设计(12)万兆UDP协议栈上板与主机网卡通信

文章目录 一、设置IP以及MAC二、上板效果2.1、板卡与主机数据回环测试2.2、板卡满带宽发送数据 一、设置IP以及MAC 顶层模块设置源MAC地址 module XC7Z100_Top#(parameter P_SRC_MAC 48h01_02_03_04_05_06,parameter P_DST_MAC 48hff_ff_ff_ff_ff_ff )(input …

【Docker】docker compose服务编排

docker compose 简介 Dockerfile模板文件可以定义一个单独的应用容器,如果需要定义多个容器就需要服务编排。 docker swarm(管理跨节点) Dockerfile可以让用户管理一个单独的应用容器;而Compose则允许用户在一个模板&#xff08…

某赛通电子文档安全管理系统 多处 SQL注入漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

微信小程序与web-view网页进行通信的尝试

首先,微信小程序向web-view传递数据一般通过地址栏传参的形式(给src赋值或者修改hash),这样一般就已经能够满足实际开发需求了,所以这里主要探讨web-view向微信小程序传参。下面,我们从官方文档入手&#x…

C语言:项目实践(贪吃蛇)

前言: 相信大家都玩过贪吃蛇这款游戏吧,贪吃蛇是久负盛名的游戏,它也和俄罗斯方块,扫雷等游戏位列经典游戏的行列,那贪吃蛇到底是怎么实现的呢? 今天,我就用C语言带着大家一起来实现一下这款游戏…

Linux第十五章

🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C,linux 🔥座右铭:“不要等到什么都没有了…

Three.js杂记(十五)—— 汽车展览(下)

在上一篇文章Three.js杂记(十四)—— 汽车展览上 - 掘金 (juejin.cn)中主要对切换相机不同位置和鼠标拖拽移动相机焦点做了简单的应用。 那么现在聊聊该如何实现汽车模型自带的三种动画展示了,实际上可以是两种汽车前后盖打开和汽车4车门打开…

网络安全之密码学技术

文章目录 网络信息安全的概念数据加密|解密概念密码学概论密码学分类古典密码学现代密码学 现代密码学的相关概念对称加密算法对称加密算法—DES对称加密算法—3DES对称加密算法—AES对称加密算法—IDEA 非对称加密算法非对称加密算法—RSA非对称加密算法—ElGamal非对称加密算…

Centos7安装K8S集群环境

一、系统设置 1、关闭swap 临时关闭swap swapoff -a 永久关闭 注释掉 /etc/fstab 中的下面配置 #/dev/mapper/centos-swap swap swap defaults 0 0 2、 关闭SELinux kubelet不支持SELinux, 这里需要将SELinux设置为permissive模式 setenforce 0 sed -i s/^SELINUXenfo…

Flutter 从 Assets 中读取 JSON 文件:指南 [2024]

在本教程中,我们将探讨如何从 Flutter 项目中的 asset 中读取 JSON 文件。您将找到详细的解释、实际示例和最佳实践,使您的 JSON 文件处理顺利高效。那么,让我们深入了解 Flutter 和 JSON 的世界吧! 从 asset 中读取 JSON 文件 …

pkpmbs 建设工程质量监督系统 Ajax_operaFile.aspx 文件读取漏洞复现

0x01 产品简介 pkpmbs 建设工程质量监督系统是湖南建研信息技术股份有限公司一个与工程质量检测管理系统相结合的,B/S架构的检测信息监管系统。 0x02 漏洞概述 pkpmbs 建设工程质量监督系统 Ajax_operaFile.aspx接口处存在文件读取漏洞,未经身份认证的攻击者可以利用漏洞读…

使用 GitHub Actions 实现项目的持续集成(CI)

目录 什么是 GitHub Actions 基础概念 Workflow 文件 Workflow 语法 实例:编译 OpenWrt 什么是 GitHub Actions GitHub Actions 是 GitHub 推出的持续集成(Continuous Integration,简称 CI)服务它允许你创建自定义工作流&am…

SpringBoot 自定义 HandlerMethodArgumentResolver 搞定xml泛型参数解析

文章目录 介绍一、解析简单 xml 数据案例引入 Jackson 的 xml 支持定义 Message 对象&MessageHeader 对象定义 Controller 方法调用结果 二、解析带泛型的 XML 数据案例2.1 直接给 Message 加上泛型 T2.2 无法直接解析泛型参数了 三、自定义 MVC 的参数解析器实现泛型参数解…

全志ARM-蜂鸣器

sh操作准备: 1.使Tab键的缩进和批量对齐为4格 在/etc/vim/vimrc 中添加一项配置 set tabstop 4; 也可以再加一行 set nu显示代码的行数 vim的设置,修改/etc/vim/vimrc文件,需要用超级用户权限 /etc/vim/vimrc set shiftwidth4 设置批量…

助力企业部署国产云原生数据库 XSKY星辰天合与云猿生完成产品互兼容认证

近日,北京星辰天合科技股份有限公司(简称:XSKY 星辰天合)与杭州云猿生数据有限公司(简称“云猿生”)完成了产品互兼容认证,星辰天合企业级分布式统一数据平台 XEDP 与云猿生的开源数据库管控平台…

CJSON工具类

4.4.3.CJSON工具类 OpenResty提供了一个cjson的模块用来处理JSON的序列化和反序列化。 官方地址: https://github.com/openresty/lua-cjson/ 1)引入cjson模块: local cjson require "cjson"2)序列化: …

竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

文章目录 0 简介1 二维码检测2 算法实现流程3 特征提取4 特征分类5 后处理6 代码实现5 最后 0 简介 🔥 优质竞赛项目系列,今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖,适合作为竞赛课…

网络层 --- IP协议

目录 1. 前置性认识 2. IP协议 3. IP协议头格式 3.1. 4位版本 3.2. 4位首部长度 3.3. 8位服务类型 3.4. 16位总长度 3.5. 8位生存时间 TTL 3.6. 8位协议 3.7. 16位首部检验和 3.8. 32位源IP和32位目的IP 4. 分片问题 4.1. 为什么要分片 4.2. 分片是什么 4.2.1. …

HTTP/1.1,HTTP/2.0和HTTP/3.0 各版本协议的详解(2024-04-24)

1、HTTP介绍 HTTP 协议有多个版本,目前广泛使用的是 HTTP/1.1 和 HTTP/2,以及正在逐步推广的 HTTP/3。 HTTP/1.1:支持持久连接,允许多个请求/响应通过同一个 TCP 连接传输,减少了建立和关闭连接的消耗。 HTTP/2&#…

win10 配置OpenCV LNK2019 无法解析的外部符号 “void __cdecl cv::imshow

1 遇到问题 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误 LNK2019 无法解析的外部符号 “void __cdecl cv::imshow(class std::basic_string<char,struct std::char_traits,class std::allocator > const &,class cv::debug_build_guard::_InputArray…