gorm实现Scanner/Valuer接口存取数组类型和自定义类型数据

在使用 GORM 时,存取数组或自定义类型的数据需要一些额外的处理。GORM 本身并不直接支持数组或复杂类型的字段,但可以通过以下几种方式实现:

1. 使用 gorm:"serializer" 标签

GORM 提供了 serializer 标签,可以将复杂类型序列化为 JSON 或其他格式存储在数据库中。

  1. package main
  2. import (
  3. "gorm.io/driver/sqlite"
  4. "gorm.io/gorm"
  5. )
  6. type User struct {
  7. gorm.Model
  8. Name string
  9. Tags []string `gorm:"serializer:json"`
  10. }
  11. func main() {
  12. db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
  13. if err != nil {
  14. panic("failed to connect database")
  15. }
  16. db.AutoMigrate(&User{})
  17. // 创建用户
  18. user := User{Name: "John", Tags: []string{"golang", "backend", "devops"}}
  19. db.Create(&user)
  20. // 查询用户
  21. var result User
  22. db.First(&result, "name = ?", "John")
  23. println(result.Tags[0]) // 输出: golang
  24. }

2. 自定义数据类型

你可以通过实现 Scanner 和 Valuer 接口来定义自定义数据类型。

  1. package main
  2. import (
  3. "database/sql/driver"
  4. "encoding/json"
  5. "errors"
  6. "gorm.io/driver/sqlite"
  7. "gorm.io/gorm"
  8. )
  9. type StringArray []string
  10. func (s *StringArray) Scan(value interface{}) error {
  11. bytes, ok := value.([]byte)
  12. if !ok {
  13. return errors.New("failed to scan StringArray")
  14. }
  15. return json.Unmarshal(bytes, s)
  16. }
  17. func (s StringArray) Value() (driver.Value, error) {
  18. return json.Marshal(s)
  19. }
  20. type User struct {
  21. gorm.Model
  22. Name string
  23. Tags StringArray
  24. }
  25. func main() {
  26. db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
  27. if err != nil {
  28. panic("failed to connect database")
  29. }
  30. db.AutoMigrate(&User{})
  31. // 创建用户
  32. user := User{Name: "John", Tags: []string{"golang", "backend", "devops"}}
  33. db.Create(&user)
  34. // 查询用户
  35. var result User
  36. db.First(&result, "name = ?", "John")
  37. println(result.Tags[0]) // 输出: golang
  38. }

3. 使用关联表

如果数组或自定义类型的数据比较复杂,可以考虑使用关联表来存储。

  1. package main
  2. import (
  3. "gorm.io/driver/sqlite"
  4. "gorm.io/gorm"
  5. )
  6. type User struct {
  7. gorm.Model
  8. Name string
  9. Tags []Tag `gorm:"many2many:user_tags;"`
  10. }
  11. type Tag struct {
  12. gorm.Model
  13. Name string
  14. }
  15. func main() {
  16. db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
  17. if err != nil {
  18. panic("failed to connect database")
  19. }
  20. db.AutoMigrate(&User{}, &Tag{})
  21. // 创建用户和标签
  22. tags := []Tag{{Name: "golang"}, {Name: "backend"}, {Name: "devops"}}
  23. user := User{Name: "John", Tags: tags}
  24. db.Create(&user)
  25. // 查询用户
  26. var result User
  27. db.Preload("Tags").First(&result, "name = ?", "John")
  28. println(result.Tags[0].Name) // 输出: golang
  29. }

总结

  • gorm:"serializer:json":适用于简单的数组或自定义类型。
  • 自定义数据类型:适用于需要更复杂逻辑的场景。
  • 关联表:适用于复杂的数据结构或需要查询的场景。

根据你的需求选择合适的方式来实现数组或自定义类型数据的存取。

声明: 本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
Golang

实现go标准库sort的方法对自定义结构体进行排序

2025-2-10 11:19:35

Golang

golang通过websocket将Jenkins构建日志实时输出到浏览器

2025-2-11 16:46:00

0 条回复 A文章作者 M管理员
欢迎您,新朋友,感谢参与互动!
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
私信列表
搜索