概述
IOC
就是Inversion of Control
的缩写,就是控制反转。在项目没有使用IOC
之前,对象D依赖对象C,对象C依赖对象B,对象B依赖对象A,这种称为依赖发现。IOC
的思想是借助”第三方”实现具有依赖关系对象之间的解耦。在引入IOC容器
之前,对象B依赖于对象A,那么需要主动创建对象A提供,创建和使用对象A的方式都由程序来控制执行。在引入IOC容器
后,对象A、B、C、D所需要的对象都由IOC容器
提供,此时对象ABCD之间失去了直接联系,当对象B需要对象A时IOC容器
会创建一个对象A注入到对象B需要的地方。因此IOC容器
就好像”粘合剂”一样,同时我们可以看出之前对象B需要对象A从主动创建对象A,到IOC容器
主动创建对象A注入到对象B所需要的地方,控制权反转来过来所以称为控制反转。面向接口编程
思路是你早就知道需求总是要变动的。修改项目
ioc
来初始化,例如说Mysql redis的初始化;然后还有Gin以及其中间件的初始化(注册路由)。type UserHandler struct {
svc service.UserService
}
xxx
// 注册路由
func (h *UserHandler) RegisterRoutes(server *gin.Engine) {
ug := server.Group("/v2/users/")
ug.POST("/signin", h.SignIn)
ug.POST("/loginin", h.Login)
ug.POST("/loginsms/code/send", h.SendSMS)
ug.POST("/loginsms", h.VerifySMS)
}
UserHandler
的结构体中写上UserService
,在UserService
中定义好各种接口,如这里写的是Signup
方法的实现,继续执行到repository
层,再到dao
层。// Serivce层
type UserService interface {
Signup(ctx context.Context, u domain.User) error
Login(ctx context.Context, email string, password string) (domain.User, error)
FindOrCreate(ctx context.Context, phone string, id string) (domain.User, error)
}
xxx
func (svc *userService) Signup(ctx context.Context, u domain.User) (err error) {
id := snowflake.GenId()
hashStr, err := bcrypt.GetPwd(u.Password)
if err != nil {
return err
}
u.Password = hashStr
u.ID = strconv.Itoa(id)
return svc.repo.Create(ctx, u)
}
// repository层
type UserRepository interface {
Create(ctx context.Context, u domain.User) error
FindByEmail(ctx context.Context, email string) (domain.User, error)
FindByPhone(ctx context.Context, phone string) (domain.User, error)
}
func (repo *CacheUserRepository) Create(ctx context.Context, u domain.User) (err error) {
return repo.dao.Insert(ctx, u)
}
dao
层就开始操作数据库了。如下面这里是用Mysql实现的。那如果要改成其他数据库实现呢?// dao层
type UserDAO interface {
Insert(ctx context.Context, u domain.User) error
FindByEmail(ctx context.Context, email string) (domain.User, error)
FindByPhone(ctx context.Context, phone string) (domain.User, error)
}
func NewUserDAO(db *gorm.DB) UserDAO {
return &GORMUserDAO{
db: db,
}
}
func (dao *GORMUserDAO) Insert(ctx context.Context, u domain.User) (err error) {
if err = dao.db.WithContext(ctx).Create(&u).Error; err != nil {
log.Println(err)
return err
}
return nil
}
dao
层接口的实现就可以了,之前service层、repository层的代码都不需要改了。type RedisUserDAO struct {
rdb *redis.Cmdable
}
func NewRedisUserDAO(rdb *redis.Cmdable) *RedisUserDAO {
return &RedisUserDAO{rdb: rdb}
}
func (rdb *RedisUserDAO) Insert(ctx context.Context, u domain.User) (err error) {
xxx
}
func (rdb *RedisUserDAO) FindByEmail(ctx context.Context, u domain.User) (domain.User, error) {
xxx
}
func (rdb *RedisUserDAO) FindByPhone(ctx context.Context, u domain.User) (domain.User, error) {
xxx
}
写在最后
本人是新手小白,如果这篇笔记中有任何错误或不准确之处,真诚地希望各位读者能够给予批评和指正。谢谢!练习的代码放在这里–↓
https://github.com/FengZeHe/LearnGolang/tree/main/project/BasicProjectV2
原文始发于微信公众号(ProgrammerHe):IOC与面向接口编程在Go的简单实现
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/260521.html