Go Gin&Gorm: Route Model Binding

sethsandaru

Seth Phat

Posted on May 14, 2022

Go Gin&Gorm: Route Model Binding

Howdy guys,

From my daily work, I'm using PHP & Laravel. One of the feature that I really like & helpful is "Route Model Binding".

Basically, you just need to define your routes and add the Model into the path, magic happens, you'll:

  • Get the Model instance and ready-to-use in the Controllers/Middlewares/Requests.
  • Receive 404 not found if the record didn't exists.

With Go, we have to build things for our needs, indeed.

Inspired by Laravel Route Model Binding, I built a Middleware for Gin which will help me to achieve that and I don't have to do Find then return error if not exists from the Controller. Extracted that to another layer.

Repo for the Middleware - sethsandaru/go-route-model-binding

Please give it a ⭐ if you actually like/going to use it πŸ’–

Feature

Eg: users/:user => Find the User model instance

  • If exists: bind it to the Gin's context via c.Set so you can retrieve it
  • If not: return 404 resource not found

It definitely makes our life easier, doesn't it? I hate to do like: "find record, not exists/error => return 404" in the controller, cuz it's not fun and make my controller's methods a bit longer

  • Q: Does it support multiple params eg: "users/:user/update-categories/:category"?
  • A: Yes

Mapping - Explicit Binding

Since it won't be as smart as Laravel's way. We need to define a map in order to map your route params with a gORM model.

var routeModelMapping = map[string]modelMapping{
    "entity": makeModelMapping(&models.Entity{}, "uuid"),
    "user": makeModelMapping(&model.User{}, "uuid"),
    // ...
}
Enter fullscreen mode Exit fullscreen mode

Access from Controllers

I love the term Controller and always using MVC in all of my applications.

func (controller *entityController) Show(c *gin.Context) {
    entity, _ := c.Get("entity")
    respondOk(c, entity)
}
Enter fullscreen mode Exit fullscreen mode
func (controller *userController) Show(c *gin.Context) {
    user, _ := c.Get("user")
    respondOk(c, user)
}
Enter fullscreen mode Exit fullscreen mode

In order to get the correct type, we have to do typeAssertion - guide here

Conclusions

  • PROs:
    • Automatically retrieve Model instances using gORM
    • 404 not found will be returned if instance not found
    • Extracted the find and check exists out of the Controller
  • CONs:
    • Have to do typeAssertion in order to get the real type

Hopefully you'll like this, just like me hehee.

Once again, here is the repo Middleware - sethsandaru/go-route-model-binding

Please give it a ⭐ if you actually like/going to use it πŸ’–

I'm using that Middleware from my open-source project (WIP) Pheasant - Dynamic CRUD Management

Have a nice weekend and happy go-coding!

πŸ’– πŸ’ͺ πŸ™… 🚩
sethsandaru
Seth Phat

Posted on May 14, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related