GORM 自定义数据类型json-切片(数组)

文章目录

  • 自定义数据类型
    • 自定义json
      • 结构体定义
      • Scaner和Valuer接口的实现
      • 插入数据&查询数据
    • 自定义切片
      • 存储切片
        • json形式存储
        • 字符串存储
    • 创建&查询数据

gorm官方文档:自定义数据类型

自定义数据类型

  数据空中很多情况下数据是多变的,我们这篇文章将以json和数组为例学习GORM的自定义数据类型方法。
  自定义的数据类型必须实现 ScannerValuer 接口,以便让 GORM 知道如何将该类型接收、保存到数据库
  通过两个接口将json、数组转换为字符串类型,其实际为序列化和反序列化的过程

自定义json

结构体定义

// Info json的序列化与反序列化的实例,定义Info的信息,方便后续进行转化及查询
type Info struct {Status     string `json:"status"`Addr       string `json:"addr"`Age        int    `json:"age"`LiveOrDead bool   `json:"liveOrDead"`
}// User 定义User表,表中的Info字段想要传入的即为json类型的数据
type User struct {Name stringInfo Info `gorm:"type:string"` //这里由于我们已经实现了Scanner和Valuer接口,当不属于基本数据类型的数据传入时,会自动调用这两个接口,自动赋予类型。当然我们这里也可以提前指定好,我们这里选择string类型
}

Scaner和Valuer接口的实现

// Scan 从数据库读取,将数据库中读取出来的数据类型还原为json,实现了sql.Scanner 接口
func (i *Info) Scan(value interface{}) error {v, _ := value.([]byte) //类型断言,断定为[]byte类型,我们在value方法中也是转换为[]byte类型输入到数据库中的var receiver Infoerr := json.Unmarshal(v, &receiver) //反序列化,将[]byte类型转化为我们需要的结构体if err != nil {return err}//fmt.Println(receiver)*i = receiver //将其内容传输给inforeturn nil}// Value 存入数据库,将json转换为数据库可接受类型数据,实现dirver.Valuer接口
func (i Info) Value() (driver.Value, error) {return json.Marshal(i) //由结构体转换为json类型数据,返回[]byte}

插入数据&查询数据

生成(迁移)表格的方式不变,插入、查询记录的方式也与之前都相同
插入数据

wang2 := User{Name: "wang2",Info: Info{Status:     "ok",Addr:       "zibo",Age:        18,LiveOrDead: true,}}DB.AutoMigrate(&User{})
DB.Create(&wang2)

查询数据

var QueryUser User
DB.Take(&QueryUser)//这里直接选择第一条内容作为演示
fmt.Printf("类型:%T\n内容:%v", QueryUser.Info, QueryUser)
//类型:main.Info
//内容:{wang2 {ok zibo 18 true}}

自定义切片

存储切片

json形式存储

  比较方便的一种存储方式就是将数组转化为json类型的数据进行存储
  大部分的代码都与json数据的存储一致,这里将所有代码贴在下面,并标注出不同

package mainimport ("database/sql/driver""encoding/json""fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger"
)var DB *gorm.DBfunc init() {username := "root"password := "123456"host := "127.0.0.1"port := 3306Dbname := "gorm"timeout := "10s"dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Info),})if err != nil {fmt.Println("连接数据库失败, error=", err)return}DB = dbfmt.Println("数据库连接成功")
}type Ports [3]string//定义一个字符串类型的数组type HostModel struct {ID    intIP    stringPorts Ports
}
//前文json格式的存储,有不懂的可以参照这里所写的
/*// Info json的序列化与反序列化的实例,定义Info的信息,方便后续进行转化及查询
type Info struct {Status     string `json:"status"`Addr       string `json:"addr"`Age        int    `json:"age"`LiveOrDead bool   `json:"liveOrDead"`
}// User 定义User表,表中的Info字段想要传入的即为json类型的数据
type User struct {Name stringInfo Info `gorm:"type:string"` //这里由于我们已经实现了Scanner和Valuer接口,当不属于基本数据类型的数据传入时,会自动调用这两个接口,自动赋予类型。当然我们这里也可以提前指定好,我们这里选择string类型
}*/func main() {G15 := HostModel{ID:    1,IP:    "192.168.1.1",Ports: [3]string{"1", "2", "3"},}DB.AutoMigrate(&HostModel{})DB.Create(&G15)var QueryUser HostModelDB.Take(&QueryUser)fmt.Printf("类型:%T\n内容:%v", QueryUser.Ports, QueryUser)//类型:main.Info//内容:{wang2 {ok zibo 18 true}}
}//注意Scan方法传入为指针,而value直接传入结构体
@@@@@@@    传入scan和value的形参是这唯一不同的    @@@@@@@@@@
// Scan 从数据库读取,将数据库中读取出来的数据类型还原为json,实现了sql.Scanner 接口
func (i *Ports) Scan(value interface{}) error {v, _ := value.([]byte) //类型断言,断定为[]byte类型,我们在value方法中也是转换为[]byte类型输入到数据库中的var receiver Portserr := json.Unmarshal(v, &receiver) //反序列化,将[]byte类型转化为我们需要的结构体if err != nil {return err}//fmt.Println(receiver)*i = receiver //将其内容传输给inforeturn nil}// Value 存入数据库,将json转换为数据库可接受类型数据,实现dirver.Valuer接口
func (i Ports) Value() (driver.Value, error) {return json.Marshal(i) //由结构体转换为json类型数据,返回[]byte}
字符串存储

  使用分割符进行数组数据的分割,这里只有scan和value函数的实现方法有区别,结构体的定义并不发生改变

知识回顾:
  切片的底层就是一个数组,所以我们可以基于数组通过切片表达式得到切片。 切片表达式中的low和high表示一个索引范围(左包含,右不包含),也就是下面代码中从数组a中选出1<=索引值<4的元素组成切片s,得到的切片长度=high-low,容量等于得到的切片的底层数组的容量。
  为了方便起见,可以省略切片表达式中的任何索引。省略了low则默认为0;省略了high则默认为切片操作数的长度:
  a[2:] // 等同于 a[2:len(a)]
  a[:3] // 等同于 a[0:3]
  a[:] // 等同于 a[0:len(a)]

// Scan 从数据库读取,将数据库中读取出来的数据类型还原为json,实现了sql.Scanner 接口
func (i *Ports) Scan(value any) error {//v := value.(string) //!!!!错误版本,????类型断言,断定为[]byte类型,我们在value方法中也是转换为[]byte类型输入到数据库中的//panic: interface conversion: interface {} is []uint8, not stringv := value.([]byte) //我们在Scan函数中value的断言都选择[]byte方法cache := strings.Split(string(v), "|") //将v转变为字符串之后用|分隔符分割,还原为[]string类型数据*i = cache//fmt.Println(cache)return nil}// Value 存入数据库,将json转换为数据库可接受类型数据,实现dirver.Valuer接口
func (i Ports) Value() (driver.Value, error) {return strings.Join(i, "|"), nil //由结构体转换为json类型数据,返回string
}

创建&查询数据

这里与json数据的写法一致

G15 := HostModel{IP:    "192.168.1.1",Ports: []string{"1", "2", "3"},
}DB.AutoMigrate(&HostModel{})
DB.Create(&G15)var QueryUser HostModel
DB.Take(&QueryUser)
fmt.Printf("类型:%T\n内容:%v", QueryUser.Ports, QueryUser)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/205677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt::UniqueConnection和lambda一块用无效

如果槽函数是lambda。 那么用了Qt::UniqueConnection也会出现槽函数被多次调用的问题。 原因&#xff1a; 参考官方文档&#xff1a; QObject Class | Qt Core 5.15.16https://doc.qt.io/qt-5/qobject.html#connect

在Go中导入软件包

引言 对于任何广泛使用的编程语言,乃至整个开源社区来说,在不同项目之间借用和共享代码的能力都是基础。借用代码使程序员能够将大部分时间花在针对自己的需求编写代码上,而且通常他们的一些新代码最终会对其他人有用。然后他们可能决定将这些可重用的部分组织成一个单元,…

在c和c++中‘->‘是什么意思?

1.->是什么 箭头符号 -> 通常用于 C、C 和类似的编程语言中&#xff0c;表示指向结构体或类的指针成员的访问。这个符号是一个简写形式&#xff0c;可以看作是两个操作的组合&#xff1a; 解引用&#xff08;dereferencing&#xff09;&#xff1a;通过一个指针来访问它…

k8s-service 7

由控制器来完成集群的工作负载&#xff0c;service&#xff08;微服务&#xff09;是将工作负载的应用暴露出去&#xff0c;从而解决访问问题 作用&#xff1a;无论是在集群内还是集群外&#xff0c;都可以访问pod上的应用&#xff0c;其实现对集群内的应用pod自动发现和负载均…

jQuery ajax读取本地json文件 三级联动下拉框

步骤 1&#xff1a;创建本地JSON文件 {"departments": [{"name": "会计学院","code": "052"},{"name": "金融学院","code": "053"},{"name": "财税学院",&qu…

【c】小红的漂亮串

#include<stdio.h> #include<string.h> int main() {char arr[1000];int count0;gets(arr);//在数组中输入字符串int lenstrlen(arr);//求字符串长度printf("%d\n",len);for(int i0;i<len;i){if(arr[i]r){if(arr[i1]e){if(arr[i2]d){countcount1;}}}}…

关于如何实现图片懒加载

图片懒加载的原理&#xff1a; 通过延迟加载图片&#xff0c;只有当图片即将进入可视区域时再进行加载&#xff0c;以优化网页加载速度和性能。 具体的实现步骤如下&#xff1a; 将待加载的图片的 src 属性设置为空或者一个占位符&#xff0c;而不是真实的图片链接。监…

要求CHATGPT高质量回答的艺术:提示工程技术的完整指南—第 19 章:聚类提示

要求CHATGPT高质量回答的艺术&#xff1a;提示工程技术的完整指南—第 19 章&#xff1a;聚类提示 聚类提示是一种允许模型根据某些特征或特性将相似数据点分组的技术。 具体做法是向模型提供一组数据点&#xff0c;并要求它根据某些特征或特性将这些数据点分组。 这种技术适…

ChatGPT可能即将发布新版本,带有debug功能:支持下载原始对话、可视化对话分支等

本文原文来自DataLearnerAI官方网站&#xff1a;ChatGPT内置隐藏debug功能&#xff1a;支持下载原始对话、可视化对话分支等 | 数据学习者官方网站(Datalearner) AIPRM的工作人员最近发现ChatGPT的客户端隐藏内置了一个新的debug特性&#xff0c;可以提高ChatGPT对话的问题调试…

AZURE==SQL managed instances

创建资源 创建DB 创建完成后&#xff0c;拿着刚才的账号密码依然连接不上 远程连接 需要开启公网访问和开放相关端口 参考Configure public endpoint - Azure SQL Managed Instance | Microsoft Learn 连接成功

Python源码分享10:使用海龟画图turtle画哆啦A梦

turtle模块是一个Python的标准库之一&#xff0c;它提供了一个基于Turtle graphics的绘图库。Turtle graphics是一种流行的绘图方式&#xff0c;它通过控制一个小海龟在屏幕上移动来绘制图形。 turtle模块可以让您轻松地创建和控制海龟图形&#xff0c;从而帮助您学习Python编…

使用xshell连接虚拟机(服务器)

作者&#xff1a;余小小 Xshell Xshell [1] 是一个强大的安全终端模拟软件&#xff0c;它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机的安全连接以及它创新性的设计和特色帮助用户在复杂的网络环境中享受他们的工作。 Xshell可以…

SpringDataJPA基础

简介 Spring Data为数据访问层提供了熟悉且一致的Spring编程模版&#xff0c;对于每种持久性存储&#xff0c;业务代码通常需要提供不同存储库提供对不同CURD持久化操作。Spring Data为这些持久性存储以及特定实现提供了通用的接口和模版。其目的是统一简化对不同类型持久性存储…

计算年year、月month和日day对应的是该年的第几天

自定义1个函数day_of_year(year, month, day)&#xff0c;计算并返回年year、月month和日day对应的是该年的第几天。 函数接口定义&#xff1a; int day_of_year(year, month, day);year, month, day分别为输入的年&#xff0c;月&#xff0c;日 裁判测试程序样例&#xff1a…

华清远见嵌入式学习——QT——作业1

作业要求&#xff1a; 代码&#xff1a; ①&#xff1a;头文件 #ifndef LOGIN_H #define LOGIN_H#include <QWidget> #include <QLineEdit> //行编辑器类 #include <QPushButton> //按钮类 #include <QLabel> //标签类 #include <QM…

图像处理之把模糊的图片变清晰

1.图片如果是有雾化效果的对图像产生影响的,要先进行图形增强,Retinex是基于深度神经网络了,我在之前图形处理的文章一路从神经网络(概率统计)—>积卷神经网络(对区域进行概率统计,对图片进行切割多个识别对象)–>深度积卷神经网络(RetinexNet也是模拟人脑的处理过程,增加…

Spark例子

Spark例子 以下是一个简单的AI Spark例子&#xff1a; 假设我们有一个数据集&#xff0c;包含房屋大小、卧室数量和售价。我们想使用Spark来预测房屋售价。 首先&#xff0c;我们需要导入所需的库和数据。在这个例子中&#xff0c;我们将使用Pyspark。 python from pyspark…

Hive增强的聚合、多维数据集、分组和汇总

Hive多维分析 1、多维分析概述2、GROUPING SETS多维分组3、GROUPING__ID函数4、ROLLUP与CUBE语法糖5、多维分析常见问题与解决春雨惊春清谷天,夏满芒夏暑相连;秋处露秋寒霜降,冬雪雪冬小大寒。今天是2023年的最后一个节气:大雪。大雪节气之后,全国气温显著下降,北方冷空气…

图表管理功能(前后端实现增删改查)

图表管理功能&#xff08;前后端实现增删改查&#xff09; 后端 库表设计 create table chart (id bigint auto_increment comment idprimary key,goal text null comment 分析目标,chartData text …

css弹窗动画效果,示例弹窗从底部弹出

从底部弹出来&#xff0c;有过渡动画效果 用max-height可以自适应内容的高度&#xff0c;当内容会超过最大高度时可以在弹窗里加个scroll-view 弹窗不能用v-if来隐藏&#xff0c;不然transition没效果&#xff0c;transition只能对已有dom元素起效果&#xff0c;所以用透明和v…