likes
comments
collection
share

[GORM]自定义类型读写——Scanner/Valuer

作者站长头像
站长
· 阅读数 49

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)
}

执行后,数据库中的记录如图所示��

[GORM]自定义类型读写——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{}
    db.Model(&School{}).Find(&sch)
    fmt.Println(sch)
}

取得的数据:

[GORM]自定义类型读写——Scanner/Valuer

注意事项

  1. 基本数据类型(string,[]string,int64,boolean等)需要起别名才能使用Scanner和Valuer。
  2. 实现方法的时候要注意Scanner和Valuer的参数、返回值数量、返回值类型、参数类型。
  3. Valuer中对数据的处理方式要和Scanner中的处理方式匹配,否则可能无法正确处理数据。
转载自:https://juejin.cn/post/7378696051081560104
评论
请登录