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.hqwc.cn/news/125832.html

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

相关文章

Qt之显示PDF文件

之前使用过mupdf库,能够成功显示pdf,但是我用着有BUG,不太理解它的代码,搞了好久都不行。后面又试了其他库,如pdfium、popler、下载了很多例程,都跑不起来!后面偶然得知xpdf库,看起来…

数据科学家的编程语言

数据科学家的编程语言 在今天有256种编程语言可供选择,选择要学习的语言可能会令人不知所措和困难。有些语言更适用于构建游戏,而有些更适用于软件工程,还有一些更适用于数据科学。 编程语言的类型 低级编程语言是计算机用来执行操作的最容…

@ConfigurationProperties配置绑定~

ConfigurationProperties注解是Spring Boot中的一个注解,用于将配置文件中的属性值绑定到Java类中的字段上。 ConfigurationProperties注解的作用包括: 实现配置文件属性和Java类字段的映射,简化了读取配置文件的操作。 可以指定配置文件中…

vue3 中使用echarts图表——柱状图

柱状图是比较常用的图形结构&#xff0c;所以我先收集一些精美的柱状图 一、柱状图&#xff1a;设置圆角和颜色 <template><div class"box" ref"chartDom"></div> </template> <script setup> import { ref, onMounted } fr…

CSS波浪进度条

目录 1. &#x1f310; 介绍 2. &#x1f3d7;️ HTML结构 3. &#x1f3a8; 页面样式 4. &#x1f4e6; 容器和波浪 5. &#x1f30a; 波浪效果 6. &#x1f4ca; 进度文本 7. &#x1f504; 旋转动画 8. &#x1f31f; 整体效果 9. &#x1f389; 结论 获取完整代码…

使用Scipy优化梯度下降问题

目 录 问题重述 附加问题 步骤实施 1.查看Scipy官网SciPy&#xff0c;找到优化有关的模块&#xff08;Optimize&#xff09; 2.研究多种优化策略&#xff0c;选择最符合代码的方案进行优化 3.minimize函数参数及其返回值 4.代码展示 5.结果展示 6.进一步优化 6.1对…

NEFU数字图像处理(1)绪论

一、简介 1.1什么是数字图像 图像是三维场景在二维平面上的影像。根据其存储方式和表现形式&#xff0c;可以将图像分为模拟图像和数字图像两大类 图像处理方法&#xff1a;光学方法、电子学方法 模拟图像&#xff1a;连续的图像数字图像&#xff1a;通过对时间上和数值上连续…

边缘计算网关

一、项目整体框架图 二、项目整体描述 边缘计算网关项目主要实现了智能家居场景和工业物联网场景下设备的数据采集和控制。 整个项目分为三大层&#xff1a;用户接口层、网关层、设备层。 其中用户层通过QT客户端、WEB界面及阿里云提供数据展示和用户接口。 网关使用虚拟机代替…

使用GDIView排查GDI对象泄漏导致的程序UI界面绘制异常问题

目录 1、问题说明 2、初步分析 3、查看任务管理器&#xff0c;并使用GDIView工具分析 4、GDIView可能对Win10兼容性不好&#xff0c;显示的GDI对象个数不太准确 5、采用历史版本比对法&#xff0c;确定初次出现问题的时间点&#xff0c;并查看前一天的代码修改记录 6、将…

Java日期的学习篇

关于日期的学习 目录 关于日期的学习JDK8以前的APIDate Date常用APIDate的API应用 SimpleDateFormatSimpleDateFormat常用API测试 反向格式化(逆操作)测试 训练案例需求(秒杀活动)实现 Calendar需求痛点常见API应用测试 JDK8及以后的API(修改与新增)为啥学习(推荐使用)新增的AP…

Linux系统下xxx is not in the sudoers file解决方法

文章目录 遇到问题解决方法参考 遇到问题 服务器上新建用户&#xff0c;名为lishizheng&#xff0c;现在想给该用户添加sudo权限。 $ sudo lsof -i tcp:7890 [sudo] password for lishizheng: lishizheng is not in the sudoers file. This incident will be reported.解决…

FFmpeg 命令:从入门到精通 | FFmpeg 解码流程

FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 解码流程 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 解码流程流程图FFmpeg 解码的函数FFmpeg 解码的数据结构补充小知识 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 解码流程 本内容参考雷霄骅博士的 FFmpeg 教程。 流…