问题描述
需要将结构体中某个字段命名为切片类型,同时需要将该字段存入数据库中,应该如何做?
type ProjectDetail struct {
ProjectDetailID uint64 `gorm:"column:id"`
ProjectDetailSort string `json:"projectSort" gorm:"column:project_detail_sort"`
ProjectDetailName string `json:"projectName" gorm:"column:project_detail_name"`
ProjectDetailPerson Person `json:"Member" gorm:"column:project_detail_person;type:text"`
ProjectDetailIntro string `json:"Introduction" gorm:"column:project_detail_intro"`
ProjectDetailIdea string `json:"Creativity" gorm:"column:project_detail_idea"`
ProjectDetailAdv string `json:"Advantage" gorm:"column:project_detail_adv"`
ProjectDetailTea TPerson `json:"Instructor" gorm:"column:project_detail_teacher;type:text"`
}
type Person []string
type TPerson []string
目标实现:
解决方法
通过重新自定义类型Tperson和Person,通过Scan() 和 Value() 两个方法使其能够在数据库和应用程序之间进行序列化和反序列化操作。
// 调用database/sql 包中的Scanner方法,
//当从数据库中查询结果中读取“Person”的类型列值时,这个方法会调用
//他接受一个接口类型的参数,该参数包含了从数据库读取的原始数据,将value转化为字符切片,
//然后再反序列化为Person类型的值
func (p *Person) Scan(value interface{
}) error{
byteValue,_ := value.([]byte)
return json.Unmarshal([]byteValue,p)
}
//同样时实现database/sql包中的valuer接口方法,当Person 类型的值写入数据库列的时候,这个方法会被调用
//使用json.marshal 将Person中的类型值序列化为字节切片,然后将其作为driver.value返回
func (p Person) Value() (driver.Value,error){
return json.Marshal(p)
}
注意点: 第二个方法不要用指针去接收,我们并没有对Person的值进行修改,而是将其序列化为字符切片并返回,因此用的是值接受者而不是指针接收者。 同时database/sql 包的valuer接口方法期望返回一个值类型,而不是指针类型,因此使用值类型接受者,如果使用指针接收者就会出现报错,·Error 1241 (21000): Operand should contain 1 column(s)·