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

问题描述 投票:0回答:3

在项目中使用

go
gorm

我创建了一个

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


当前代码

  • Get
    方法来自
    FirstDao
    for
    first
    表和
    FirstModel

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

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

我想要达到的目标

想知道有没有可能用一个

BaseDao
方法在go中写一个
Get()
,这样我就不用把这段代码写2次了。

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


我试过的

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

问题

  • 可以这样做吗?
  • 如果不是,为什么?
  • 如果是,怎么样?
go inheritance go-gorm code-reuse
3个回答
3
投票

如果你试图完全绕过为每个 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
}

1
投票
type BaseDao struct {
    FirstDao
    SecondDao
}

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

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


0
投票

也许不能。因为在 go 1.18 之前 go dose 不支持 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){}

它导致

import cycle
在dao和model之间

© www.soinside.com 2019 - 2024. All rights reserved.