Akash Shinde
Akash Shinde

Reputation: 955

Golang abstraction in handler to avoid code duplication

I am trying to implement abstraction in golang I am using gorm orm library and gin framework

Base Class

type Base struct {
  Context *gin.Context // Passing gin request
}

func (b *Base ) Add() {
   err := b.Context.BindJSON(b)
   if err != nil {
     // handling error here
   }
   gorm.db.Create(b) // Here I am adding base data to database
}

Child Class

type Shopper struct { 
   Base  // Embedding Base struct
   Name string,
   Address string,
   ContactNo int
}

Handler

 func handler (c *gin.Context) {
  s := new(Shopper)
  s.Context = c
  s.Add()  // Here I am expecting Add() method should bind JSON to shopper struct
           // entry to database using gorm
 }

Add() method is not taking any property which shopper struct has.

Here I just want to avoid code duplication in each handler which just takes json from request body and add to respective database using gorm

Upvotes: 1

Views: 1431

Answers (1)

kostix
kostix

Reputation: 55443

You can't because Go does not have inheritance.

Let me repeat: Go does not have inheritance, so please unlearn this "base" and "child" stuff when working with Go.

The reason your code does not work is that while the method set of an embedded type is indeed "lifted" and merged into the method set of the type which embeds it, when any of such methods is called its receiver is the value of the embedded type and not the value of the enclosing type.

IOW your Add() method always receives values of type Base

If the enclosing type has a method which has the same name as a method of the embedded type, and you call such method on a value of the enclosing type, the method of the enclosing type will be called. So there's no overloading but there's "overriding" if you want.

What I'd do in your situation is stop thinking in OOP and wrote a function rather than a method (untested):

func add(any interface{}, ctx *gin.Context) {
   err := ctx.BindJSON(any)
   if err != nil {
     // handling error here
   }
   gorm.db.Create(any) // Here I am adding base data to database
}

Then in your handler:

func handler (c *gin.Context) {
  s := new(Shopper)
  s.Context = c
  add(s, c)
}

Upvotes: 3

Related Questions