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.mzph.cn/news/96718.shtml

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

相关文章

美国各流域边界下载,并利用arcgis提取与处理

一、边界数据的下载 一般使用最普遍的流域边界数据是从HydroSHEDS官网下载: HydroBASINS代表一系列矢量多边形图层,以全球尺度呈现次级流域边界。该产品的目标是提供一种无缝的全球覆盖,其中包含了不同尺度(从数十到数百万平方千米&#xf…

Zygote Secondary:加速应用启动的未来之路

Zygote Secondary:加速应用启动的未来之路 1. 引言 在现代的移动应用开发中,启动速度和响应性能是用户体验的重要方面。然而,传统的 Android 进程管理方式在启动应用时会出现性能瓶颈,导致启动时间过长和资源占用过多。为了解决…

Linux基本指令(中)——“Linux”

各位CSDN的uu们好呀,今天,小雅兰的内容是Linux基本指令呀!!!下面,让我们进入Linux的世界吧!!! cp指令(重要) mv指令(重要&#xff09…

“益路同行”栏目专访 第06期—小星星关爱联盟创始人魏洁荣老师

中国善网在本届(第十届)慈展会上特别推出了《益路同行》采访栏目,《益路同行》栏目旨在寻觅公益之路上同行者的故事,挖掘公益更深层次的内涵,探索新时代公益发展道路。希望公益企业、人物、故事被更多人看到&#xff0…

外卖小程序源码vs定制开发:何时选择哪种方式?

在数字餐饮行业的蓬勃发展中,外卖应用程序已经成为餐厅和创业者的必备工具。然而,当涉及到开发外卖应用程序时,您会面临一个重要的决策:是使用外卖小程序源码还是进行定制开发?这两种方法各有优势和劣势,取…

Python3 Selenium4 chromedriver Pycharm闪退的问题

Python3版本:3.11.5 Pycharm版本:2023.2.1 Chrome版本:117.0.5938.150(正式版本) 在使用最新版的Selenium4版本时,chromedriver可以驱动Chrome但是闪退,Selenium目前最新版本是4.13.0&#…

【刷题笔记10.5】LeetCode:排序链表

LeetCode:排序链表 一、题目描述 给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。 二、分析 这题咱们默认要求:空间复杂度为O(1)。所以这把咱们用自底向上的方法实现归并排序,则可以达到O(1) 的空间复杂…

【Vue/React】浅谈Vue/React中的Diff算法以及key的作用和index不适合作为key的原因

Diff算法 Vue 和 React 都是基于 vdom 的前端框架,组件渲染会返回 vdom,渲染器再把 vdom 通过增删改的 api 同步到 dom。 当状态发生改变时,react会根据【新的状态】生成【新的虚拟DOM】 然后将新旧虚拟DOM进行 diff比较,比较规则…

【itext7】使用itext7将多个PDF文件、图片合并成一个PDF文件,图片旋转、图片缩放

这篇文章,主要介绍使用itext7将多个PDF文件、图片合并成一个PDF文件,图片旋转、图片缩放。 目录 一、itext7合并PDF 1.1、引入依赖 1.2、合并PDF介绍 1.3、采用字节数组方式读取PDF文件 1.4、合并多个PDF文件 1.5、合并图片到PDF文件 1.6、旋转图…

王杰C++day1

#include <iostream>using namespace std;int main() {cout << "输入一个字符串&#xff1a;" << endl;string str;int a 0,b 0,c 0,d 0,e 0;getline(cin,str);for(int i 0;i < (int)str.size();i){if(str[i] > A && str[i] &…

接口自动化测试介入项目管理流程

上图为接口自动化测试介入梧桐项目管理流程图 前景和目标&#xff1a; 现在公司的项目流程都是全部开发完成后提交到测试环境进行测试&#xff0c;导致测试人员在开发编码过程中相对清闲&#xff0c;除了完成测试用例之外没有其他事情可做&#xff0c;而当进入测试阶段又会变…

兽药经营小程序微信商城的作用是什么

无论家宠还是畜牧养殖&#xff0c;生病杀虫总是不可少的&#xff0c;尤其对铲屎官们来说&#xff0c;宠物的健康状况很重要&#xff0c;以此花费百元千元也并不觉心疼&#xff0c;兽药的需求度也是非常高&#xff0c;那么对相关从业商家来说&#xff0c;遇到的难题有哪些&#…

Java ES 滚动查询

滚动查询&#xff08;Scroll Query&#xff09;是 Elasticsearch 提供的一种机制&#xff0c;用于处理大量数据的查询。它允许你在多个请求之间保持“游标”&#xff0c;以便在后续请求中获取更多的结果。 以下是滚动查询的基本工作原理&#xff1a; 1 初始查询: 客户端发送一…

Sql server 使用DBCC Shrinkfile 收缩日志文件

磁盘空间有限&#xff0c;需要收缩日志文件释放空间。 数据库名称上右击属性->文件,逻辑名称日志文件默认名称为“_log”结尾。 alter database 数据库 set recovery simple dbcc shrinkfile(XXX_log,2,truncateonly) alter database 数据库 set recovery full

系统架构设计:1论软件系统建模方法及其应用

目录 一 论点论据 1结构化建模 2信息工程建模 3面向对象建模 4功能分解法 <

安全基础 --- MySQL数据库的《锁》解析

MySQL的ACID &#xff08;1&#xff09;ACID是衡量事务的四个特性 原子性&#xff08;Atomicity&#xff0c;或称不可分割性&#xff09;一致性&#xff08;Consistency&#xff09;隔离性&#xff08;Isolation&#xff09;持久性&#xff08;Durability&#xff09; &…

数据结构与算法(七)--使用链表实现栈

一、前言 之前我们已经学习了链表的所有操作及其时间复杂度分析&#xff0c;我们可以了解到对于链表头的相关操作基本都是O(1)的&#xff0c;例如链表头增加、删除元素&#xff0c;查询元素等等。那我们其实有一个数据结构其实可以完美利用到这些操作的特点&#xff0c;都是在…

大数据学习,涉及哪些技术?

学习大数据需要涉及多种技术和概念&#xff0c;因为大数据领域非常广泛&#xff0c;涵盖了数据的采集、存储、处理、分析和可视化等多个方面。以下是学习大数据时需要考虑的一些关键技术和概念&#xff1a; 1、数据采集和存储&#xff1a; 数据库管理系统&#xff08;DBMS&am…

Python与数据分析--Pandas操作进阶

目录 1.文件读取方式 1.1.绝对路径读取文件 1.2.相对路径读取文件 2.列表数据操作 2.1.列索引指定 2.2.代码数据对齐 3.创建新CSV文件 4.缺失值处理 4.1.缺失值创建 4.2.缺失值检索 4.3.缺失值查询 4.3.1.isnull()函数判断 4.3.2.notnull()函数判断 4.3.3.any()函数…

在win10里顺利安装了apache2.4.41和php7.4.29以及mysql8.0.33

一、安装apache和php 最近在学习网站搭建。其中有一项内容是在windows操作系统里搭建apachephp环境。几天前根据一本书的上的说明尝试了一下&#xff0c;在win10操作系统里安装这两个软件&#xff1a;apache2.4.41和php7.4.29&#xff0c;安装以后apche能正常启动&#xff0c;…