gin + gorm 實現單模型的curd的父類控制器

wuyan94zl發表於2021-09-26

廢話不會說,上程式碼

父類控制器 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 協議》,轉載必須註明作者和本文連結
沒有造飛機的格局,怎麼能擰得好螺絲。

相關文章