gorm 自定义时间、字符串数组类型

文章目录

    • 自定义时间类型
    • 自定义字符串数组
    • 测试与完整代码
      • 测试代码
      • 测试结果

GORM 是GO语言中一款强大友好的ORM框架,但在使用过程中内置的数据类型不能满足以下两个需求,如下:

  1. time.Time类型返回的是 2023-10-03T09:12:08.53528+08:00这种字符串格式,需要额外处理,我们更希望默认的是是2023-10-03 09:12:08这种可读性更高的格式
  2. 有些数据字段需要存储数组形式,如下Article Tags字段希望保存不确定个字符串。直接保存会提示[error] unsupported data type: &[]

官方提供了 ScannerValuer两个接口,来满足自定义数据的存储、提取,本文记录上述两种结构解决方法。

type Article struct {Tags  []string
}

自定义时间类型

自定义时间类型需满足以下两个需求:

  • 返回2006-01-02 15:04:05格式
  • CreatedAtUpdatedAt使用时能按GORM规范自动填充当前时间

默认的time.Time是能被gorm自动存储,取出到结构体的,返回2023-10-03T09:12:08.53528+08:00格式原因是在于json序列化时,这里解决方案是自定义一个数据结构,添加JSON Marshal接口,但是自定义的数据类型gorm不能识别,所以要额外添加gorm ScannerValuer两个接口

type CustomTime time.Time// GORM Scanner 接口, 从数据库读取到类型
func (t *CustomTime) Scan(value any) error {if v, ok := value.(time.Time); !ok {return errors.Errorf("failed to unmarshal CustomTime value: %v", value)} else {*t = CustomTime(v)return nil}
}// GORM Valuer 接口, 保存到数据库
func (t CustomTime) Value() (driver.Value, error) {if time.Time(t).IsZero() {return nil, nil}return time.Time(t), nil
}// JSON Marshal接口,CustomTime结构体转换为json字符串
func (t *CustomTime) MarshalJSON() ([]byte, error) {t2 := time.Time(*t)return []byte(fmt.Sprintf(`"%v"`, t2.Format("2006-01-02 15:04:05"))), nil
}

自定义字符串数组

代码比较简单,直接定义一个类型实现 ScannerValuer两个接口,使用中将列定义为Strings类型即可

type Strings []stringfunc (s *Strings) Scan(value any) error {v, _ := value.(string)return json.Unmarshal([]byte(v), s)
}
func (s Strings) Value() (driver.Value, error) {b, err := json.Marshal(s)return string(b), err
}

测试与完整代码

测试代码

package mainimport ("database/sql/driver""encoding/json""fmt""time""github.com/pkg/errors""github.com/glebarez/sqlite""gorm.io/gorm"
)type Strings []stringfunc (s *Strings) Scan(value any) error {v, _ := value.(string)return json.Unmarshal([]byte(v), s)
}
func (s Strings) Value() (driver.Value, error) {b, err := json.Marshal(s)return string(b), err
}type CustomTime time.Time// GORM Scanner 接口, 从数据库读取到类型
func (t *CustomTime) Scan(value any) error {if v, ok := value.(time.Time); !ok {return errors.Errorf("failed to unmarshal CustomTime value: %v", value)} else {*t = CustomTime(v)return nil}
}// GORM Valuer 接口, 保存到数据库
func (t CustomTime) Value() (driver.Value, error) {if time.Time(t).IsZero() {return nil, nil}return time.Time(t), nil
}// JSON Marshal接口,CustomTime结构体转换为json字符串
func (t *CustomTime) MarshalJSON() ([]byte, error) {t2 := time.Time(*t)return []byte(fmt.Sprintf(`"%v"`, t2.Format("2006-01-02 15:04:05"))), nil
}// fmt.Printf, 【可选方法】
func (t CustomTime) String() string {return time.Time(t).Format("2006-01-02 15:04:05")
}type Article struct {ID        uint `gorm:"primaryKey"`Tags      StringsCreatedAt CustomTimeUpdatedAt CustomTime
}func main() {db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})if err != nil {panic("failed to connect database")}db.AutoMigrate(&Article{})db.Create(&Article{Tags: []string{"go", "java"}})var article Articledb.Last(&article)fmt.Printf("article is: %v\n", article)b, _ := json.Marshal(&article)fmt.Printf("article json is: %s\n", string(b))time.Sleep(time.Second * 30)article.Tags = append(article.Tags, "python")db.Save(&article)db.Last(&article)fmt.Printf("updated article is: %v\n", article)b, _ = json.Marshal(&article)fmt.Printf("updated article json is: %s\n", string(b))
}

测试结果

字符串数组

在这里插入图片描述

自定义时间,可以看到满足2006-01-02 15:04:05格式输出,以及时间自动添加和更新
在这里插入图片描述

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

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

相关文章

FreeRTOS入门教程(队列详细使用示例)

文章目录 前言一、队列基本使用二、如何分辨数据源三、传输大块数据总结 前言 上篇文章我们已经讲解了队列的概念和队列相关的API函数,那么本篇文章的话就开始带大家来学习使用队列。 一、队列基本使用 这个例子将会创建三个任务,其中两个任务用来发送…

完美清晰,炫酷畅享——Perfectly Clear Video为你带来卓越的AI视频增强体验

在我们日常生活中,我们经常会拍摄和观看各种视频内容,无论是旅行记录、家庭聚会还是商务演示,我们都希望能够呈现出最清晰、最精彩的画面效果。而现在,有一个强大的工具可以帮助我们实现这一目标,那就是Perfectly Clea…

谁“动”了我的信息?

通信公司“内鬼” 批量提供手机卡 超6万张手机卡用来发涉赌短信 2023年10月2日,据报道2022年12月,湖北省公安厅“雷火”打击整治治安突出问题专项行动指挥部研判发现,有人在湖北随州利用虚拟拨号设备GOIP发出大量赌博短信。随州市公安局研判…

【数据结构--八大排序】之快速排序

💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …

Flink--9、双流联结(窗口联结、间隔联结)

星光下的赶路人star的个人主页 我还有改变的可能性,一想起这点,我就心潮澎湃 文章目录 1、基于时间的合流——双流联结(Join)1.1 窗口联结(Window Join)1.2 间隔联结(Interval Join)…

苹果手机怎么备份所有数据?2023年iPhone 15数据备份常用的3种方法!

当苹果手机需要进行刷机、恢复出厂设置、降级iOS系统等操作时,我们需要将自己的iPhone数据提前进行备份。 特别是在苹果发布新iOS系统时,总有一些小伙伴因为升降级系统,而导致了重要数据的丢失。 iPhone中储存着重要的照片、通讯录、文件等数…

出去重复的列值(关键词:distinct)

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 语法格式: select distinct 列名 from 表名; 案例:查询emp表中,员工的职位(job),并去重…

Redis-分布式锁

分布式锁相关内容 超卖问题切入可以使用互斥锁给先获取到锁的线程加锁吗?使用redis分布式锁解决超卖问题setnx命令实现分布式锁为什么需要设置过期时间?Redis实现分布式锁如何合理控制锁的有效时长 redisson实现分布式锁 超卖问题切入 我们先来看一个项目…

【Docker内容大集合】Docker从认识到实践再到底层原理大汇总

前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量博客汇总https://blog.csdn.net/yu_cblog/categ…

前端TypeScript学习day01-TS介绍与TS部分常用类型

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 TypeScript 介绍 TypeScript 是什么 TypeScript 为什么要为 JS 添加类型支持? TypeScript 相…

【已解决】spring-boot项目使用maven打包时出现BOOT-INF文件夹的问题

jar中多了这个BOOT-INF文件夹的原因,主要是因为我们在maven的pom文件中加入了spring-boot-maven-plugin这个插件,如下所示: 只需要将加个configuration标签,并在里面嵌套加入一个skip子标签,并将skip的值设为true&…

vulnhub靶机doubletrouble

下载地址:doubletrouble: 1 ~ VulnHub 主机发现 arp-scan -l 端口扫描 nmap --min-rate 1000 -p- 192.168.21.151 端口服务扫描 nmap -sV -sT -O -p22,80 192.168.21.151 漏洞扫描 nmap --scriptvuln -p22,80 192.168.21.151 先去看看web页面 这里使用的是qdpm …

如何一步步优化负载均衡策略

发展到一定阶段后,Web 应用程序就会增长到单服务器部署无法承受的地步。这时候企业要么提升可用性,要么提升可扩展性,甚至两者兼而有之。为此,他们会将应用程序部署在多台服务器上,并在服务器之前使用负载均衡器来分配…

pycharm配置python3.8版本专门用于undecteded_chromedriver测试

pycharm配置python3.8版本专门用于undecteded_chromedriver测试 作者:虚坏叔叔 博客:https://pay.xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 一、Pycharm及python环境的配置 1.安装python-3.8.7rc1-amd64.e…

医学影像归档与通讯系统(PACS)系统源码 PACS三维图像后处理技术

医学影像归档与通讯系统(PACS)系统源码 PACS三维图像处理 医学影像归档与通讯系统(PACS)系统,是一套适用于从单一影像设备到放射科室、到全院级别等各种应用规模的医学影像归档与通讯系统。PACS集患者登记、图像采集、…

NUWA论文阅读

论文链接:NUWA: Visual Synthesis Pre-training for Neural visUal World creAtion 文章目录 摘要引言相关工作视觉自回归模型视觉稀疏自注意 方法3D数据表征3D Nearby Self-Attention3D编码器-解码器训练目标 实验实现细节与SOTA比较T2I微调T2V微调V2V微调Sketch-t…

基于SpringBoot的信息化在线教学平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 学生信息管理 教师信息管理 学生成绩管理 留言板 学生注册管理 留言反馈 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已…

数据结构 2.1 单链表

1.单链表 线性表:1.有限的序列 2.序列中的每一个元素都有唯一的前驱和后继,除了开头和结尾的两个节点。 顺序表:分配一块连续的内存去存放这些元素,eg、数组 链表:内存是不连续的,元素会各自被分配一块内…

vue3 element-ui-plus Carousel 跑马灯 的使用 及 踩坑记录

vue3 element-ui-plus Carousel 跑马灯 的踩坑记录 Carousel 跑马灯首页跑马灯demo Carousel 跑马灯 首先&#xff0c;打开其官网-跑马灯案例 跑马灯代码&#xff1a; <el-carousel :interval"5000" arrow"always"><el-carousel-item v-for"…

【高级rabbitmq】

文章目录 1. 消息丢失问题1.1 发送者消息丢失1.2 MQ消息丢失1.3 消费者消息丢失1.3.1 消费失败重试机制 总结 2. 死信交换机2.1 TTL 3. 惰性队列3.1 总结&#xff1a; 4. MQ集群 消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1. 消息丢失问题 1.1…