Go语言中GORM存取数组/自定义类型数据

 更新时间:2023年01月17日 09:28:09   作者:Go~Go~Go~  
在使用gorm时往往默认的数据类型不满足我们的要求,需要使用一些自定义数据类型作为字段类型,下面这篇文章主要给大家介绍了关于Go语言中GORM存取数组/自定义类型数据的相关资料,需要的朋友可以参考下

GORM存取数组类型数据

GORM不支持数组类型变量数据的存取,可以通过GROM的自定义数据类型实现。

一、GORM的自定义类型

1. Scanner/Valuer接口

GORM的自定义的数据类型必须实现Scanner/Valuer接口。

(1) Scanner接口的Scan方法,是从数据库读取数据到Go变量时需要进行的解析处理,与解码的过程类型。

(2) Valuer接口的Value方法,是将Go变量存到数据库时进行编码处理。

2. 数组变量

​ 虽然GORM不支持数组变量,但是可以通过实现Scanner/Valuer接口,在数据库取/存时进行类似解码/编码的处理,使数组变量成为数据库可支持的变量类型。

(1) 实现Sacnner接口

Scan函数,从数据库读取数据后,对其进行处理,然后获得Go类型的变量。

type Strs []string

func (m *Strs) Scan(val interface{}) error {
	s := val.([]uint8)
	ss := strings.Split(string(s), "|")
	*m = ss
	return nil
}

如上自定义Strs类型,底层类型未字符串数组。Scan函数将读取的val值,按照字符串处理,以"|"为分隔符进行切割,获得字符串数组类型,然后使用指针赋值。

(2) 实现Valuer接口

Value函数,将数据存到数据库时,对数据进行处理,获得数据库支持的类型。

func (m Strs) Value() (driver.Value, error) {
	str := strings.Join(m, "|")
	return str, nil
}

如上将Strs存入数据库前,将数组内的字符串用"|"拼接,获得数据库支持的string类型后再存入数据库。

3. 测试

定义如下函数进行测试

(1) 模型变量

type User struct {
	ID   uint `gorm:"primary_key"`
	Name string
	Pics Strs `gorm:"type:longtext"`  // 自定义的数组类型,在数据库中存为长文本类型
}

​ (2) Service函数

func SaveUser(user User) error {
	var err error
	err = db.Save(&user).Error
	return err
}

func GetUser(name string) (User, error) {
	var user User
	err := db.First(&user, "name = ?", name).Error
	return user, err
}

​ (3) testService函数

func TestSaveUser() {
   user := User{
      Name: "Jason",
      Pics: Strs{
         "123124",
         "gtsrbxrzsfcv",
      },
   }
   err := SaveUser(user)
   if err != nil {
      log.Panicln("保存失败!", err)
   } else {
      log.Println("保存成功!")
   }
}

func TestGetUser() {
   user, err := GetUser("Jason")
   if err != nil {
      log.Panicln("获取失败!", err)
   } else {
      log.Println("获取成功!", user)
   }
}

​ (4) 运行结果

2022/07/30 18:18:41 保存成功!
2022/07/30 18:18:41 获取成功! {3 Jason [123124 gtsrbxrzsfcv]}

在数据库存储中体现为:

mysql> select *from users;
+----+-------+---------------------+
| id | name  | pics                |
+----+-------+---------------------+
|  3 | Jason | 123124|gtsrbxrzsfcv |
+----+-------+---------------------+
1 row in set (0.00 sec)

二、实际生产

上面的例子中展示了Scanner/Valuer接口的简单使用,实际生产中将数组类型转换为json字符串进行保存,下面展示一个完整的例子,以一个User拥有一张包含信息的银行卡为例(当然可以通过一对一关联4444实现)。

(1) 实现自定义类型

type User struct {
   ID    uint `gorm:"primary_key"`
   Name  string
   Cards Card `gorm:"json"`
}

type Card struct {  // 指定json的Tag。
   Type     int    `json:"type"`
   Account  string `json:"account"`
   Password string `json:"password"`
}

// Scan 解码json字符串
func (card *Card) Scan(val interface{}) error {
   b, _ := val.([]byte)
   return json.Unmarshal(b, card)
}

// Value 编码json
func (card Card) Value() (value driver.Value, err error) {
	return json.Marshal(card)
}

​ (2) 数据表模型

type User struct {
   ID    uint `gorm:"primary_key"`
   Name  string
   Cards Card `gorm:"json"`  // 指定为json类型
}

​总结

到此这篇关于Go语言中GORM存取数组/自定义类型数据的文章就介绍到这了,更多相关GORM存取数组 自定义类型数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go语言日志实现详解(打印日志、日志写入文件和日志切割)

    go语言日志实现详解(打印日志、日志写入文件和日志切割)

    golang内置了log包,实现简单的日志服务,下面这篇文章主要给大家介绍了关于go语言日志实现(打印日志、日志写入文件和日志切割)的相关资料,需要的朋友可以参考下
    2022-10-10
  • Go语言实现一个简单的并发聊天室的项目实战

    Go语言实现一个简单的并发聊天室的项目实战

    本文主要介绍了Go语言实现一个简单的并发聊天室的项目实战,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 浅谈golang的http cookie用法

    浅谈golang的http cookie用法

    本篇文章主要介绍了golang的http cookie用法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • Golang定制化zap日志库使用过程分析

    Golang定制化zap日志库使用过程分析

    Zap是我个人比较喜欢的日志库,是uber开源的,有较好的性能,在项目开发中,经常需要把程序运行过程中各种信息记录下来,有了详细的日志有助于问题排查和功能优化,但如何选择和使用性能好功能强大的日志库,这个就需要我们从多角度考虑
    2023-03-03
  • Go 高效截取字符串的一些思考

    Go 高效截取字符串的一些思考

    这篇文章主要介绍了Go 高效截取字符串的一些思考,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • golang常用库之gorilla/mux-http路由库使用详解

    golang常用库之gorilla/mux-http路由库使用详解

    这篇文章主要介绍了golang常用库之gorilla/mux-http路由库使用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Go-ethereum 解析ethersjs中产生的签名信息思路详解

    Go-ethereum 解析ethersjs中产生的签名信息思路详解

    这篇文章主要介绍了Go-ethereum 解析ethersjs中产生的签名信息,我们解析签名的需要知道,签名的消息,签名,和公钥,按照这个思路,我们可以通过ethers实现消息的签名,也可以通过go-ethereum实现,需要的朋友可以参考下
    2022-08-08
  • Go基于GORM 获取当前请求所执行的 SQL 信息(思路详解)

    Go基于GORM 获取当前请求所执行的 SQL 信息(思路详解)

    这篇文章主要介绍了Go基于GORM 获取当前请求所执行的 SQL 信息(思路详解),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Golang语言中fs.ReadDir的全面指南

    Golang语言中fs.ReadDir的全面指南

    欢迎来到Golang语言中fs.ReadDir的全面指南!这个简短的引导将让你掌握如何高效地使用这个功能,一起来深入探索吧,保证你会有所收获!
    2023-12-12
  • Golang try catch与错误处理的实现

    Golang try catch与错误处理的实现

    社区不少人在谈论 golang 为毛不用try/catch模式,而采用苛刻的recovery、panic、defer组合,本文就来详细的介绍一下,感兴趣的可以了解一下
    2021-07-07

最新评论