Gorm:有没有可能为常见的数据库操作(例如get by id)定义共享方法?

kse8i1jr  于 2023-03-06  发布在  Go
关注(0)|答案(3)|浏览(163)

在项目中使用gogorm
我创建了一个dao级别来 Package 数据库操作,每个表都有自己的dao类型。

当前代码

  • first表和FirstModelFirstDao中的Get方法:
func (dao *FirstDao) Get(id uint64) (*model.FirstModel, error) {
}
  • second表和SecondModelSecondDao中的Get方法:
func (dao *SecondDao) Get(id uint64) (*model.SecondModel, error) {
}

我想要达到的目标

我想知道是否有可能在go中用一个Get()方法编写一个BaseDao,这样我就不必写两遍这段代码了。
这在Java中非常容易,但是由于Go语言非常不同,并且不支持真正的继承(我猜),所以不确定这是否可能。

我所尝试的

  • 定义一个模型接口,尝试使用反射。但是失败了。

主要原因:在Get()方法内部,它仍然需要原始特定结构的示例,例如model.FirstModel{},我将其作为接口model.Model传递,并且不能将其用作原始类型。

  • 结构体嵌入。
  • 谷歌搜索

问题

  • 有可能做到吗?
  • 如果没有,原因是什么?
  • 如果是,如何处理?
toiithl6

toiithl61#

如果你试图完全绕过为每个DAO编写Get()方法,你唯一的解决方案就是从这个方法返回一个interface{}

  • 您需要手动将interface{}强制转换到所有位置。
  • 你在牺牲类型安全。

我认为最好的解决方案是通过使用结构嵌入来共享大部分代码,并为每个DAO编写轻量级 Package 器,以将不安全的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
}
11dmarpk

11dmarpk2#

type BaseDao struct {
    FirstDao
    SecondDao
}

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

只是写下我的想法。也许这会帮助你找到你的解决方案

w1e3prcc

w1e3prcc3#

也许不能。因为go在1.18之前不支持genrics。
我认为如果你想使用hook,提取dao层可能是一个反模式。
想象一下:

// pkg models
type User
type UserChangeLog

// hook
func (user *User) afterUpdate(tx) error () {
  // if you want to record user changes
  userChangeLogDao().insert(user)
}
// pkg dao
func (userDao) update() {}
func (userChangeLogDao) insert(User){}

它导致dao和模型之间import cycle

相关问题