【go】依赖倒置demo

文章目录

  • 前言
    • [1 项目目录结构:](#1 项目目录结构:)
    • [2 初始化函数](#2 初始化函数)
    • [3 router](#3 router)
    • [4 api](#4 api)
    • [5 service](#5 service)
    • [6 dao](#6 dao)
    • [7 Reference](#7 Reference)

前言

为降低代码耦合性,采用依赖注入的设计模式。原始请求路径:router -> api -> service -> dao。请求的为实际方法,具有层层依赖的关系。现将方法抽象为接口,即a依赖b,但a不创建(或销毁)b,仅使用b,b的创建(或销毁)交给容器。

1 项目目录结构:

复制代码
├─ddd
│  ├─router.go
│  │ 
│  ├─api
│  │  └─api_abstract.go   // 抽象接口
│  │  └─api_dog.go   // dog实现接口
│  │ 
│  ├─service
│  │  └─srv_abstract.go 
│  │  └─srv_dog.go  
│  │  
│  ├─dao
│  │  └─dao_abstract.go  
│  │  └─dao_dog.go  
│  │  
│  ├─model
│  │  ├─dto
│  │  └─schema

2 初始化函数

go 复制代码
// 依赖注入
func InitDog() *DogApiImpl  {
	d := dao.NewDogDaoImpl(global.DB)
	s := service.NewDogSrvImpl(d)
	return api.NewDogApiImpl(s)
}

3 router

go 复制代码
func Router() *gin.Engine {
	dog := init.InitDog()
	r.GET("/info", dog.Info)
	...
}

4 api

api_abstract.go中为抽象接口:

go 复制代码
type DogAPIIface interface {
	Create(ctx *gin.Context)
	Update(ctx *gin.Context)
	Info(ctx *gin.Context)
	List(ctx *gin.Context)
}

api_dog.go中为api的实现方法:

go 复制代码
type DogApiImpl struct {
	srv service.DogSrvIface
}

var _ DogAPIIface = (*DogApiImpl)(nil)

func NewDogApiImpl(srv service.DogSrvIface) *DogApiImpl {
	return &DogApiImpl{
		srv: srv,
	}
}

func (da *DogApiImpl) Info(ctx *gin.Context) {
	var req dto.DogInfoReq
	if err := ctx.ShouldBindUri(&req); err != nil {
		return
	}

	res, err := da.srv.Info(ctx, req.ID)
	if err != nil {
		return
	}

	helper.Response.ResponseSuccessWithData(ctx, consts.Success, res)
}

// 其他待实现方法
func (da *DogApiImpl) Create(ctx *gin.Context) {
}

...

5 service

srv_abstract.go中为抽象接口:

go 复制代码
type DogSrvIface interface {
	Create(ctx *gin.Context, req *dto.DogCreateReq) error
	Update(ctx *gin.Context, req *dto.DogUpdateReq) error
	Info(ctx *gin.Context, req *dto.DogInfoReq) (*dto.DogInfoRes, error)
	List(ctx *gin.Context, req *dto.DogListReq) ([]*dto.DogInfoRes, int, error)
}

srv_dog.go中为service的实现方法:

go 复制代码
type DogSrvImpl struct {
	dao dao.DogDaoIface
}

var _ DogSrvIface = (*DogSrvImpl)(nil)

func NewDogSrvImpl(dao dao.DogDaoIface) *DogSrvImpl {
	return &DogSrvImpl{
		dao: dao,
	}
}

func (ds *DogSrvImpl) Info(ctx *gin.Context, req *dto.DogInfoReq) (*dto.DogInfoRes, error) {
	var data dto.DogInfoReq

	// 具体业务逻辑
	dog, err := ds.dao.FindByID(ctx, id)
	if err != nil {
		return nil, err
	}

	return &dog, err
}
...

6 dao

dao_abstract.go中为抽象接口:

go 复制代码
type DogDaoIface interface {
	Create(ctx *gin.Context, req *dto.DogCreateReq) error
	Update(ctx *gin.Context, req *dto.DogUpdateReq) error
	Info(ctx *gin.Context, req *dto.DogInfoReq) (*dto.DogInfoRes, error)
	List(ctx *gin.Context, req *dto.DogListReq) ([]*dto.DogInfoRes, int, error)
}

dao_dog.go中为dao的实现方法:

go 复制代码
type DogDaoImpl struct {
	db *gorm.DB
}

var _ dao.DogDaoIface = (*DogDaoImpl )(nil)

func NewDogDaoImpl(db gorm.DB) *DogDaoImpl{
	return &DogDaoImpl{
		db: &db,
	}
}


func (ds *DogSrvImpl) Info(ctx *gin.Context, req *dto.DogInfoReq) (*dto.DogInfoRes, error) {
	
	// 具体业务逻辑
	return nil, nil
}
...

7 Reference

https://blog.hackerpie.com/posts/testing/golang-write-testable-codes/
https://juejin.cn/post/7146852457774055437

相关推荐
|_⊙几秒前
C++ 智能指针
开发语言·c++
电子科技圈4 分钟前
IAR作为Qt Group独立BU携两项重磅汽车电子应用开发方案首秀北京车展
开发语言·人工智能·汽车·软件工程·软件构建·代码规范·设计规范
代码中介商5 分钟前
C语言指针深度解析:从数组指针到函数指针
c语言·开发语言
ElevenPlus7 分钟前
【 AI智能体时代:一名Javaer的技术随想录】MCP服务部署架构
后端
Jasmine_llq20 分钟前
《B4356 [GESP202506 二级] 数三角形》
开发语言·c++·双重循环枚举算法·顺序输入输出算法·去重枚举算法·整除判断算法·计数统计算法
千寻girling20 分钟前
RabbitMQ 详细教程(38K字数)
java·后端·面试
止语Lab28 分钟前
Go vs Java GC:同一场延迟战争的两条路
java·开发语言·golang
Rust研习社29 分钟前
Rust 多线程从入门到实战
开发语言·后端·rust
卷毛的技术笔记35 分钟前
从“拆东墙补西墙”到“最终一致”:分布式事务在Spring Boot/Cloud中的破局之道
java·spring boot·分布式·后端·spring cloud·面试·rocketmq
Ulyanov1 小时前
《玩转QT Designer Studio:从设计到实战》 QT Designer Studio数据绑定与表达式系统深度解析
开发语言·python·qt