兼职20网站开发网络优化工程师为什么都说坑人
文章目录
- 前言
 - 1 项目目录结构:
 - 2 初始化函数
 - 3 router
 - 4 api
 - 5 service
 - 6 dao
 - 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 初始化函数
// 依赖注入
func InitDog() *DogApiImpl  {d := dao.NewDogDaoImpl(global.DB)s := service.NewDogSrvImpl(d)return api.NewDogApiImpl(s)
}
 
3 router
func Router() *gin.Engine {dog := init.InitDog()r.GET("/info", dog.Info)...
}
 
4 api
api_abstract.go中为抽象接口:
type DogAPIIface interface {Create(ctx *gin.Context)Update(ctx *gin.Context)Info(ctx *gin.Context)List(ctx *gin.Context)
}
 
api_dog.go中为api的实现方法:
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.DogInfoReqif 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中为抽象接口:
type DogSrvIface interface {Create(ctx *gin.Context, req *dto.DogCreateReq) errorUpdate(ctx *gin.Context, req *dto.DogUpdateReq) errorInfo(ctx *gin.Context, req *dto.DogInfoReq) (*dto.DogInfoRes, error)List(ctx *gin.Context, req *dto.DogListReq) ([]*dto.DogInfoRes, int, error)
}
 
srv_dog.go中为service的实现方法:
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中为抽象接口:
type DogDaoIface interface {Create(ctx *gin.Context, req *dto.DogCreateReq) errorUpdate(ctx *gin.Context, req *dto.DogUpdateReq) errorInfo(ctx *gin.Context, req *dto.DogInfoReq) (*dto.DogInfoRes, error)List(ctx *gin.Context, req *dto.DogListReq) ([]*dto.DogInfoRes, int, error)
}
 
dao_dog.go中为dao的实现方法:
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
