告诉Gorm如何在结构体中“读取”/“写入”接口字段。

huangapple go评论85阅读模式
英文:

Tell Gorm how to "read"/"write" an interface field in a struct

问题

假设我有以下结构体:

type User struct {
    ID      uuid.UUID
    Name    string
    Hobbies []Hobby
}

其中Hobby是一个接口,有几个实现,例如:

type ReadingHobby struct {
    ID     uuid.UUID
    userID uuid.UUID
    User   *User
    Books  ...
}

type HikingHobby struct {
    ID     uuid.UUID
    userID uuid.UUID
    User   *User
    Routes ...
}

每个爱好都存储在自己的表中,所以按照前面的例子,我们将有一个reading_hobby表和一个hiking_hobby表,它们有自己的表定义和外键。

但是,当我尝试使用gorm从User加载Hobbies时,我得到了不支持的数据类型的错误,这是有道理的,因为gorm不知道如何序列化/反序列化该字段。

我该如何实现呢?我正在尝试创建自定义的序列化器(https://gorm.io/docs/serializer.html),但我无法访问数据库来“查询”所有可能的爱好表,并获取属于用户的所有爱好。

作为最后的解决方案,我考虑使用AfterFind钩子(https://gorm.io/docs/hooks.html#Querying-an-object),但我也希望能够在需要爱好时使用Preload("Hobbies"),而不是总是通过钩子来检索它们。

有什么想法吗?

英文:

Imagine I have the following struct:

type User struct {
    ID   uuid.UUID
    Name string
    Hobbies []Hobby
}

where Hobby is an interface with several implementations, as an example:

type ReadingHobby struct {
    ID     uuid.UUID
    userID uuid.UUID
    User   *User
    Books  ...
}

type HikingHobby struct {
    ID     uuid.UUID
    userID uuid.UUID
    User   *User
    Routes ...
}

Each hobby is stored in its own table, so following the previous example, we would have a reading_hobby table, and a hiking_hobby table with their own table definition and foreign keys.

But then, when I try to load the Hobbies from an User using gorm, I get Unsopported Data type, which makes sense because gorm does not know how to serialize/deserialize that field.

How can I achieve that? I was checking to create my custom serializer (https://gorm.io/docs/serializer.html), but I don't have access to the db to "query" all the possible hobbies tables and get all the ones that belong to the user.

As a last solution I was thinking to use the AfterFind hook (https://gorm.io/docs/hooks.html#Querying-an-object), but I would also like to be able to use Preload("Hobbies") when I need the hobbies, instead of always retrieving them with the hook.

Any ideas?

答案1

得分: 1

不确定这是否适合您的需求,但我真的没有看到任何更简单的方法。

我认为我会使用两个不同的模型:

一个反映数据库的模型,您可以更轻松地处理gorm:

type User struct {
    ID   uuid.UUID
    Name string
    ReadingHobbies []ReadingHobby
    HikingHobbies []HikingHobby
    ...
}

和您原始的带有接口的结构:

type UserInterface struct {
    ID   uuid.UUID
    Name string
    Hobbies []Hobby
}

然后有一个转换器转换为接口结构:

func (u User) ToInterface() UserInterface {
	return UserInterface{
        ID: u.ID,
        ...
    }
}
英文:

Not sure if this would suit your needs, but I don't really see any easier way

I think I would go with two different models :

One reflecting the DB, with which you can more easily handle gorm :

type User struct {
    ID   uuid.UUID
    Name string
    ReadingHobbies []ReadingHobby
    HikingHobbies []HikingHobby
    ...
}

And your original struct with the interface :

type UserInterface struct {
    ID   uuid.UUID
    Name string
    Hobbies []Hobby
}

Then have a converter to the struct interfacing :

func (u User) ToInterface() UserInterface {
	return UserInterface{
        ID: u.ID,
        ...
    }
}

huangapple
  • 本文由 发表于 2023年5月9日 18:20:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76208274.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定