gin + gorm 实现单模型的curd的父类控制器

废话不会说,上代码

父类控制器 base/base.go

type Base struct {
    data  interface{}
}

func (b *Base) SetModel(data interface{}) {
    b.data = data
}

func (b *Base) Create(c *gin.Context) {
    b.setFields(c)
    gorm.DB.Create(b.data)
    c.JSON(200, b.data)
}

func (b *Base) Update(c *gin.Context) {
    b.info(c)
    b.setFields(c)
    gorm.DB.Save(b.data)
    c.JSON(200, b.data)
}

func (b *Base) Info(c *gin.Context) {
    b.info(c)
    c.JSON(200, b.data)
}

func (b *Base) Delete(c *gin.Context) {
    b.info(c)
    gorm.DB.Delete(b.data)
    c.JSON(200, "deleted")
}

func (b *Base) info(c *gin.Context) {
    id := c.Param("id")
    gorm.DB.First(b.data, id)
}

func (b *Base) setFields(c *gin.Context) {
    getType := reflect.TypeOf(b.data).Elem()
    getVal := reflect.ValueOf(b.data).Elem()
    for i := 0; i < getType.NumField(); i++ {
        if getType.Field(i).Tag.Get("action") != "" {
            v := c.DefaultPostForm(getType.Field(i).Tag.Get("json"), "")
            if v == "" {
                continue
            }
            switch getType.Field(i).Type.String() {
            case "uint64":
                if val, err := strconv.Atoi(v); err == nil {
                    getVal.Field(i).SetUint(uint64(val))
                } else {
                    panic(fmt.Sprintf("参数类型错误:%v", err))
                }
            case "string":
                getVal.Field(i).SetString(v)
            }
        }
    }
}

gorm.DB 为gorm连接MySQL实例

子类控制器 controller/user.go

// User 定义控制器 操作模型
type User struct {
    Id       uint64 `json:"id"`
    Email    string `json:"email" action:"1"`
    Password string `json:"password" action:"1"`
}

// UserController 定义控制器 结构体
type UserController struct {
    base.Base
}

// NewUser 实例化控制器
func NewUser() *UserController {
    c := &UserController{}
    c.SetModel(&User{})
    return c
}

子类控制器 controller/bolg.go

// Blog 定义控制器 操作模型
type Blog struct {
    Id     uint64 `json:"id"`
    UserId uint64 `json:"user_id" action:"1"`
    Title  string `json:"title" action:"1"`
}

// BlogController 定义控制器 结构体
type BlogController struct {
    base.Base
}

// NewBlog 实例化控制器
func NewBlog() *BlogController {
    c := &BlogController{}
    c.SetModel(&Blog{})
    return c
}

可以看到上面2个子类控制器基本一样,只需定义好该控制器需要操作的数据模型结构体就行了。

gin 路由设置

    app := gin.Default()
    // user curd
    app.PUT("user/create", func(c *gin.Context) {
        controller.NewUser().Create(c)
    })
    app.GET("user/info/:id", func(c *gin.Context) {
        controller.NewUser().Info(c)
    })
    app.POST("user/update/:id", func(c *gin.Context) {
        controller.NewUser().Update(c)
    })
    app.DELETE("user/delete/:id", func(c *gin.Context) {
        controller.NewUser().Delete(c)
    })
    // blog curd
    app.PUT("blog/create", func(c *gin.Context) {
        controller.NewBlog().Create(c)
    })
    app.GET("blog/info/:id", func(c *gin.Context) {
        controller.NewBlog().Info(c)
    })
    app.POST("blog/update/:id", func(c *gin.Context) {
        controller.NewBlog().Update(c)
    })
    app.DELETE("blog/delete/:id", func(c *gin.Context) {
        controller.NewBlog().Delete(c)
    })

以上基本完成了简单的示例,实际使用中逻辑会复杂写,可以配合struct的tag配合父类setFields函数实现复杂的逻辑。如字段验证validate等。

本作品采用《CC 协议》,转载必须注明作者和本文链接
没有造飞机的格局,怎么能拧得好螺丝。
讨论数量: 1

这个设计模式不对吧!结构体,然后是接口!你这个是结构体,接口了! 接口 是个类型,这个类型有4个方法,增删改查! 结构体就是,文章,视频,图片,他们都要调用这个接口类型,就实现了数据库借口了!

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!