处理程序中的 Golang 抽象以避免代码重复

Golang abstraction in handler to avoid code duplication

我正在尝试在 golang 中实现抽象 我正在使用 gorm orm 库和 gin 框架

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() 方法不采用 shopper 结构具有的任何 属性。

在这里我只想避免在每个 handler 中使用 code duplication 只需从请求正文中获取 json 并使用 gorm

添加到相应的 database

你不能因为 Go does not have inheritance.

再说一遍:Go 没有继承,所以在使用 Go 时请忘掉这些 "base" 和 "child" 东西。

您的代码不起作用的原因是虽然方法集 嵌入式类型确实是 "lifted" 并合并到方法集中 嵌入它的类型,当调用任何此类方法时 它的接收者是嵌入类型的值而不是 封闭类型的值。

IOW 你的 Add() 方法总是接收 Base

类型的值

如果封闭类型有一个同名的方法 作为嵌入类型的方法,你调用这样的方法 在封闭类型的值上,封闭的方法 类型将被调用。 所以没有超载,但如果你想要的话,还有 "overriding"。

在你的情况下我会做的是停止在 OOP 中思考 并编写了一个函数而不是一个方法(未经测试):

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
}

然后在您的处理程序中:

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