Gorm:是否可以为常见的数据库操作例如通过 id 获取定义共享方法? 示例

问题描述

在项目中使用 gogorm

我创建了一个 dao 级别来包装数据库操作,每个表都有自己的 dao 类型。


当前代码

  • Get 方法来自 FirstDao,用于 first 表和 FirstModel

    func (dao *FirstDao) Get(id uint64) (*model.FirstModel,error) {
    }
    
  • Get 方法来自 SecondDao,用于 second 表和 SecondModel

    func (dao *SecondDao) Get(id uint64) (*model.SecondModel,error) {
    }
    

我想要达到的目标

想知道是否可以在 go 中使用单个 BaseDao 方法编写 Get(),这样我就不必编写此代码 2 次了。

这在 Java 中很容易,但由于 go 非常不同,并且不支持真正的继承(我猜),不确定这是否可能。


我尝试了什么

  • 定义一个模型接口,并尝试使用反射。但是失败了。
    主要原因:在Get()方法内部,它仍然需要一个原始特定结构的实例,例如model.FirstModel{},我将它作为接口model.Model传递,并且不能将其作为原始类型使用.
  • 结构嵌入。
  • 谷歌搜索

问题

  • 可以这样做吗?
  • 如果不是,为什么?
  • 如果是,怎么做?

解决方法

如果您试图完全绕过为每个 DAO 编写 Get() 方法,您唯一的解决方案是从此方法返回一个 interface{}。 然而,这种方法会产生两个问题:

  • 您需要在任何地方手动投射 interface{}
  • 您正在牺牲类型安全。

我认为最好的解决方案是使用结构嵌入共享大部分代码,并为每个 DAO 编写轻量级包装器,将不安全的 interface{} 转换为类型安全的值。

示例

首先使用通用的 Get() 方法创建您的基础 DAO。 Go 中没有类型泛型,因此您应该在此处返回 interface{}

type BaseDAO struct {}

func (*BaseDAO) Get(id uint64) (interface{},error) {}

然后,对于每种类型的数据,创建一个特定的 DAO 实现,嵌入 BaseDAO :

type FooModel = string

type FooDAO struct {
    // Embbeding BaseDAO by not specifying a name on this field
    // BaseDAO methods can be called from FooDAO instances
    BaseDAO
}

func (foo *FooDAO) Get(id uint64) (FooModel,error) {
    // Call the shared Get() method from BaseDAO.
    // You can see this just like a `super.Get()` call in Java.
    result,_ := foo.BaseDAO.Get(id)
    return result.(FooModel),nil
}
,
type BaseDao struct {
    FirstDao
    SecondDao
}

func (dao *BaseDao) Get(id uint64) (*model.SecondModel,error) {
}

只是写下我的想法。可能这会帮助您找到解决方案