前言

GORM作为一个go语言里知名的orm,可谓是文档详细,功能强大,操作简单,集所有的优势于一体,几乎可以说是没什么缺点。但是吧,作为一个刚从python转语言过来的新人,在Gin+GORM映射结构体这一环节可谓是踩坑不少。首先就是,我要接收一个数组,数据库字段类型为varchar,如果结构体类型定义为string,则根本映射不到,如果是[]string,则又会出现各种各样的错误,为此我也走了不少弯路。以此篇文章来记录一下。

自定义结构体

就先不说踩的坑了,先上解决办法,这其实也是一个坑,因为我没有认真看完文档,也没有联想起来解决办法,所以导致在此卡了很久。

自定义数据类型

我们无法通过[]string或者[]map[string]interface{}来进行入库。但是我们可以自定义结构,以此通过他的编译和入库,完成我们想要的功能。

type Front struct {
	Banner []string `gorm:"type:varchar(255);not null" json:"banner" label:"Banner图"`
}

像上面这样,我们完全无法存储一个列表,即便存了,也是各种bug不断,此时就需要我们自定义类型。根据文档得知,我们要实现ValueScan方法。

type Node struct {
	List List `json:"list" `
}

type List []string

func (p List) Value() (driver.Value, error) {
	return json.Marshal(p)
}

func (p *List ) Scan(data interface{}) error {
	return json.Unmarshal(data.([]byte), &p)
}

// 将其修改为List类型。
type Front struct {
	Banner List `gorm:"type:varchar(255);not null" json:"banner" label:"Banner图"`
}

这样,我们就实现了我们想要的功能,接收["1","2","3","4"]这样的数据来存储到数据库了。

同样的,想列表嵌套数组的深层嵌套结构也可以通过自定义结构来完成。

type Hash struct {
	Name string `json:"name"`
	Link string `json:"link"`
}

type HashValue []Hash

func (p HashValue) Value() (driver.Value, error) {
	return json.Marshal(p)
}

func (p *HashValue ) Scan(data interface{}) error {
	return json.Unmarshal(data.([]byte), &p)
}

再来说说我踩过的坑,虽然没成功,但是呢,我觉得有教育意义,本来一开始定义的结构体类型为string,然后无法接收到数组数据,随后我又将其改为了空接口。虽然能够接收到数据了,但是,依旧无法入库。

然后最重要的地方来了,我的思想出现了问题,既然我无法存入空接口数组数据,那我干脆存成字符串吧,于是我使用fmt.Sprintf来将数据格式化为字符串,于是后边就针对字符串进行了各种操作,最终结果也是以失败告终。

此路不通之后,我就想着让字符串原封不动的入库,于是又将接收的结构体换成了map,通过这个终于成功的入库了,但是,问题又来了,既然是字符串,在进行序列化之后,前端会将字符串的符号进行自动的转义,针对转义问题我又进行了各种操作,从替换字符,到分割数组,卡在这里好几天。。。

总之呢,就是,只要思想不滑坡,办法总比困难多。希望大家能以此为戒。思想不要出现问题。