Gorm:是否可以为公共db操作定义共享方法(例如通过id获取)?

Gorm:是否可以为公共db操作定义共享方法(例如通过id获取)?,go,inheritance,go-gorm,code-reuse,Go,Inheritance,Go Gorm,Code Reuse,在项目中使用go和gorm 我创建了一个dao级别来包装数据库操作,每个表都有自己的dao类型 现行代码 从FirstDao中获取方法,用于first表和FirstModel: func (dao *FirstDao) Get(id uint64) (*model.FirstModel, error) { } func (dao *SecondDao) Get(id uint64) (*model.SecondModel, error) { } 从SecondDao中获取方法,用于se

在项目中使用
go
gorm

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


现行代码
  • FirstDao
    中获取
    方法,用于
    first
    表和
    FirstModel

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

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

我想要达到的目标 想知道是否可以用一个
Get()
方法在go中编写一个
BaseDao
,这样我就不必编写这段代码两次了

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


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

问题
  • 有可能这样做吗
  • 若否,原因为何
  • 如果是,如何进行
类型BaseDao结构{
第一刀
二道
}
func(dao*BaseDao)Get(id uint64)(*model.SecondModel,错误){
}
只是写下我的想法。这可能会帮助您找到解决方案

键入BaseDao结构{
第一刀
二道
}
func(dao*BaseDao)Get(id uint64)(*model.SecondModel,错误){
}

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

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

  • 您需要在任何地方手动强制转换
    接口{}
  • 你在亵渎类型安全
我认为最好的解决方案是通过使用结构嵌入来共享大部分代码,并为每个DAO编写轻量级包装器,以将不安全的
接口{}
转换为类型安全值

例子 首先使用泛型
Get()
方法创建基本DAO。 Go中没有类型泛型,因此您应该在此处返回
接口{}

type BaseDAO结构{}
func(*BaseDAO)Get(id uint64)(接口{},错误){}
然后,对于每种类型的数据,创建一个特定的DAO实现,嵌入
BaseDAO

type FooModel=string
类型FooDAO结构{
//通过不在此字段上指定名称来增强BaseDAO
//可以从FooDAO实例调用BaseDAO方法
BaseDAO
}
func(foo*FooDAO)Get(id uint64)(FooModel,error){
//从BaseDAO调用shared Get()方法。
//您可以看到这就像Java中的'super.Get()'调用一样。
结果:=foo.BaseDAO.Get(id)
返回结果(FooModel),无
}

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

  • 您需要在任何地方手动强制转换
    接口{}
  • 你在亵渎类型安全
我认为最好的解决方案是通过使用结构嵌入来共享大部分代码,并为每个DAO编写轻量级包装器,以将不安全的
接口{}
转换为类型安全值

例子 首先使用泛型
Get()
方法创建基本DAO。 Go中没有类型泛型,因此您应该在此处返回
接口{}

type BaseDAO结构{}
func(*BaseDAO)Get(id uint64)(接口{},错误){}
然后,对于每种类型的数据,创建一个特定的DAO实现,嵌入
BaseDAO

type FooModel=string
类型FooDAO结构{
//通过不在此字段上指定名称来增强BaseDAO
//可以从FooDAO实例调用BaseDAO方法
BaseDAO
}
func(foo*FooDAO)Get(id uint64)(FooModel,error){
//从BaseDAO调用shared Get()方法。
//您可以看到这就像Java中的'super.Get()'调用一样。
结果:=foo.BaseDAO.Get(id)
返回结果(FooModel),无
}

这通常是
接口{}
的用途。我不熟悉gorm,但是所有的go编码/解码和封送/解封送函数都已经使用了gorm,所以您不必担心任何反射。@super-Yep,已经找到了解决方案。这通常是
接口{}
的用途。我不熟悉gorm,但所有的go编码/解码和封送/解封送函数都已经使用了gorm,因此您不必担心任何反射。@super-yesp,已经找到了解决方案。我已经重构了代码,与答案描述的类似。现在子DAO的代码更加整洁。顺便说一句,在答案
结果中,:=foo.BaseDAO.Get(id)
,应该将模型作为第一个参数传递。我重构了与答案描述类似的代码。现在子DAO的代码更加整洁。顺便说一句,在回答
结果中,u:=foo.BaseDAO.Get(id)
,应该将模型作为第一个参数传递。