lundi 27 novembre 2023

How to write generic CRUD controller for all entities in golang?

I am creating a Go server using GoFiber to return data from MySQL database. I am using GORM library to save and fetch data from the db. I have 8 entities in total. I have defined model for these entites like this

package models

type Account struct {
    ID        uint      `json:"id" gorm:"primary_key;auto_increment;not_null"`
    Name      string    `json:"name"`
    Company   string    `json:"company"`
    GSTIN     string    `json:"gstin"`
    AccountNo string    `json:"accountNo" gorm:"unique"`
    IFSC      string    `json:"ifsc"`
    CreatedAt time.Time `json:"createdAt"`
    UpdatedAt time.Time `json:"updatedAt"`
}

Now, for each entity, I am writing 4 controller methods: Create, Update, List, Delete. It is basically the same code for each entity, just that the entity name is changing.

package controllers

// GET: List call
func GetAccounts(c *fiber.Ctx) error {
    accounts := new([]models.Account)
    result := database.DB.Find(accounts)
    if result.Error != nil {
        return result.Error
    }
    c.SendStatus(http.StatusOK)
    return c.JSON(accounts)
}

// POST
func CreateAccount(c *fiber.Ctx) error {
    account := new(models.Account)
    err := c.BodyParser(account)
    if err != nil {
        return err
    }
    result := database.DB.Create(account)
    if result.Error != nil{
        return result.Error
    }
    return c.SendStatus(http.StatusCreated)
}

Now, like this, I have written 8 x 4 =32 controller methods. All having duplicate code with just the entity name changing.

I have defined routes for each of these controllers manually as well.

    app.Post("api/account", controllers.CreateAccount)
    app.Get("api/accounts", controllers.GetAccounts)

There is definitely a better way to do this. I am not exactly sure how to do so or implement it. What interfaces should I define, what structs should I embedd, or what to do?

Aucun commentaire:

Enregistrer un commentaire