在项目中使用
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 非常不同,并且不支持真正的继承(我猜),不确定这是否可能。
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) {
}
写下我的想法。可能这会帮助您找到解决方案
也许不能。因为在 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之间