[GORM]自定义类型读写——Scanner/Valuer
GORM的自定义类型读写机制
GORM默认支持go中的int64,string等基本数据类型的读写。但有些时候我们需要直接保存某个数据,这个时候GORM就不支持了。
如果你有自定义保存格式的要求可以使用GORM提供的Scanner/Valuer完成。如果只是单纯的想以JSON形式存进数据库,可以使用GORM提供的序列化字段标签。
本篇文章将介绍使用Scanner/Valuer方法完成自定义类型读写。
Valuer
Valuer是一个接口,我们要实现该接口下面的Value方法,该方法在将go结构体数据存入数据库的时候会用到。
语法:
func (调用者 模型) Value() (driver.Value, error){
}
语法中的模型就是自定义类型,调用者是go的结构体。从调用者获取数据然后将处理完的数据返回出去即可。
例子:
结构体-Student(Scanner部分也用,故Scanner部分省略结构体定义)
type Student struct{
Id int64
Name string
Age int64
Grade int64
}
结构体-School(Scanner部分也用,故Scanner部分省略结构体定义)
我们让School保存Student的信息。
type School struct {
Id int64
StudentInfo Student `gorm:"type:Student"` //要标明类型,否则无法正确解析
}
Value代码:
func (s Student) Value() (driver.Value,error){
return fmt.Sprintf("%d-%s-%d-%d",s.Id,s.Name,s.Age,s.Grade),nil
}
Scanner
Scanner也是一个接口,我们需要实现该接口下面的Scan方法。在从数据库获取数据后回填到go结构体的时候会用到。
语法:
func (调用者 *模型) Scan(value interface{}) error{
}
语法中的“模型”就是你的自定义数据类型。这里的value就是数据库中的数值。方法体中可以写数据的处理逻辑。
处理完的数据要赋值给调用者!
例子:
func (s *Student) Scan(value interface{}) error{
student:=value.(String)
strs:=strings.Split(student,"-")
s.Id,_=strconv.ParseInt(strs[0],10,64)
s.Name,_=strs[1]
s.Age, _ = strconv.ParseInt(data_splited[2], 10, 64)
s.Grade, _ = strconv.ParseInt(data_splited[3], 10, 64)
return nil
运行
在Scanner和Valuer都写完后,运行主程序
func main(){
//连接的是sqlite数据库
_, err := os.Open("./db/sys.db")
if !os.IsExist(err) {
os.Mkdir("./db", 0777)
}
db, _ := gorm.Open(sqlite.Open("./db/sys.db"))
db.AutoMigrate(&entity.School{}) //自动创建数据表
sch := School{StudentInfo:Student{Age: 17, Name: "张三",Grade:9}}
db.Save(&sch)
}
执行后,数据库中的记录如图所示��
获取数据代码:
func main(){
//连接的是sqlite数据库
_, err := os.Open("./db/sys.db")
if !os.IsExist(err) {
os.Mkdir("./db", 0777)
}
db, _ := gorm.Open(sqlite.Open("./db/sys.db"))
//db.AutoMigrate(&entity.School{}) //自动创建数据表
sch := School{}
db.Model(&School{}).Find(&sch)
fmt.Println(sch)
}
取得的数据:
注意事项
- 基本数据类型(
string
,[]string
,int64
,boolean
等)需要起别名才能使用Scanner和Valuer。 - 实现方法的时候要注意Scanner和Valuer的参数、返回值数量、返回值类型、参数类型。
- Valuer中对数据的处理方式要和Scanner中的处理方式匹配,否则可能无法正确处理数据。
转载自:https://juejin.cn/post/7378696051081560104