Golang: Generics in Go
Hi devs, I will be writing an interesting article on how generics helped me solve a challenging problem while I was working on a simple REST API project built with GoLang using the gin framework. The problem /* model.go */ type LoginAuth struct { USERNAME string `bson:"username" json:"username" validate:"required,min=1"` PASSWORD string `bson:"username" json:"password" validate:"required,min=4"` } /* controller.go */ var user model.LoginAuth if err := c.BindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } The code snippet above is from an authentication controller. My goal is to reuse this code snippet below with other resources's controllers with different types. e.g Comment controller with model.Comment type var user model.LoginAuth if err := c.BindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } The Solution func bindJSONData[T any](c *gin.Context) (T, bool) { var data T if err := c.BindJSON(&data); err != nil { utils.AbortResponse(c, utils.Reponse{StatusCode: http.StatusUnprocessableEntity, Success: false, Message: err.Error(), Data: nil}) return *new(T), false } return data, true } I created a generic function bindJSONData that takes a type parameter T. This T represents the struct type we want to bind the JSON data to. Inside the function, I declared a variable data of type T. The c.BindJSON(&data) call remains the same, but now it dynamically binds to the type specified by T. The function now returns both the bound data of type T and a boolean indicating success. This makes the calling code cleaner. If binding fails, it returns the zero value of type T and false. Hope this post helps. Feel free to leave a comment on this post I will be in the comment section.

Hi devs,
I will be writing an interesting article on how generics helped me solve a challenging problem while I was working on a simple REST API project built with GoLang using the gin framework.
The problem
/* model.go */
type LoginAuth struct {
USERNAME string `bson:"username" json:"username" validate:"required,min=1"`
PASSWORD string `bson:"username" json:"password" validate:"required,min=4"`
}
/* controller.go */
var user model.LoginAuth
if err := c.BindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
The code snippet above is from an authentication controller.
My goal is to reuse this code snippet below with other resources's controllers with different types.
e.g Comment controller with model.Comment type
var user model.LoginAuth
if err := c.BindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
The Solution
func bindJSONData[T any](c *gin.Context) (T, bool) {
var data T
if err := c.BindJSON(&data); err != nil {
utils.AbortResponse(c, utils.Reponse{StatusCode: http.StatusUnprocessableEntity, Success: false, Message: err.Error(), Data: nil})
return *new(T), false
}
return data, true
}
- I created a generic function bindJSONData that takes a type parameter T.
- This T represents the struct type we want to bind the JSON data to.
- Inside the function, I declared a variable data of type T.
- The c.BindJSON(&data) call remains the same, but now it dynamically binds to the type specified by T.
- The function now returns both the bound data of type T and a boolean indicating success. This makes the calling code cleaner.
- If binding fails, it returns the zero value of type T and false.
Hope this post helps. Feel free to leave a comment on this post I will be in the comment section.