持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
🎐 放在前面说的话
大家好,我是北 👧🏻
本科在读,此为日常捣鼓.
如有不对,请多指教,也欢迎大家来跟我讨论鸭 👏👏👏
还有还有还有很重要的,麻烦大可爱们动动小手,给北点颗心心♥,北北需要鼓励嗷呜~
今天我们来浅谈一下代码过程中遇到直接定义model数组/切片类型,存不进MySQL数据库怎么办?怎么解决?
Let’s get it!
出现问题:
在使用gorm包定义的数据库的结构如下:
type Todo struct {
gorm.Model
UID uint // 用户 ID
Title string `json:"title" binding:"min=1,max=64"` // 文章标题
Content string `json:"content" binding:"min=1,max=512"` // 内容
Tag []string `json:"tag" binding:"required"` // 标签
Deadline uint `json:"deadline"` // 截止时间
}
go run 时,报错(sql: converting argument $1 type: unsupported type []string, a slice of string)
分析原因:
mysql中不支持[]string 类型的数据,不可以直接在结构体中定义[]string类型。
解决方案
基于gorm 库的特性,可以通过自定义JSON类型将数据传入,因此解决步骤一共分为两步:
- step 1:将
[]string类型编码为JSON类型数据; - step 2:自定义
JSON类型数据,使得gorm可以支持,可以参考GORM-自定义数据类型
step 1: 首先将结构体中数据类型定义改为一个新的自定义类型
type Tag []string
/**
* @description: todos 数据表
*/
type Todo struct {
gorm.Model
UID uint // 用户 ID
Title string `json:"title" binding:"min=1,max=64"` // 文章标题
Content string `json:"content" binding:"min=1,max=512"` // 内容
Tag Tag `json:"tag" binding:"required"` // 标签
Deadline uint `json:"deadline"` // 截止时间
}
step 2:自定义一个JSON类型,可以参考GORM-自定义数据类型
我们 step 1把Tag自定义为type Tag []string,但是这种类型在gorm中还不可以直接识别,所以需要进一步自定义数据类型。
func (t *Tag) Scan(value interface{}) error {
bytesValue, _ := value.([]byte)
return json.Unmarshal(bytesValue, t)
}
func (t Tag) Value() (driver.Value, error) {
return json.Marshal(t)
}
Scan()存入数据库前转为 stringValue()读出数据前转为 json 说白了就是,我们不是直接的把[]string类型的数据直接存入MySQL数据库,而是自定义成一个json类型,存储前,我们把它转为string,取出时,我们把转变为我们需要的json。(一共有3个步骤)就是这么一个简单的原理啦!
gorm官方文档中的自定义数据类型
GORM 提供了少量接口,让开发者能够自定义GORM 支持的数据类型
实现自定义数据类型由以下两个函数实现
Scan()Value()
自定义的数据类型必须实现 Scanner 和 Valuer 接口,以便让 GORM 知道如何将该类型接收、保存到数据库
🎉 放在后面说的话
报错sql: converting argument $1 type: unsupported type []string, a slice of string怎么办?来,我们用gorm自定义数据类型来解决它。仅需Scanner和Valuer两个接口,便可把你想要的数组或切片类型存储进MySQL数据库!本文我从问题报错、分析原因、解决办法,拓展运用知识为你解愁~