使用 GoFrame ORM 对返回结果为空判断非常简便,大部分场景下直接判断返回的数据是否为 nil 或者长度为 0,或者使用 IsEmpty/IsNil 方法。

一、数据集合(多条)

  1. r, err := g.Model("order").Where("status", 1).All()
  2. if err != nil {
  3. return err
  4. }
  5. if len(r) == 0 {
  6. // 结果为空
  7. }

也可以使用 IsEmpty 方法:

  1. r, err := g.Model("order").Where("status", 1).All()
  2. if err != nil {
  3. return err
  4. }
  5. if r.IsEmpty() {
  6. // 结果为空
  7. }

二、数据记录(单条)

  1. r, err := g.Model("order").Where("status", 1).One()
  2. if err != nil {
  3. return err
  4. }
  5. if len(r) == 0 {
  6. // 结果为空
  7. }

也可以使用 IsEmpty 方法:

  1. r, err := g.Model("order").Where("status", 1).One()
  2. if err != nil {
  3. return err
  4. }
  5. if r.IsEmpty() {
  6. // 结果为空
  7. }

三、数据字段值

返回的是一个”泛型”变量,这个只能使用 IsEmpty 来判断是否为空了。

  1. r, err := g.Model("order").Where("status", 1).Value()
  2. if err != nil {
  3. return err
  4. }
  5. if r.IsEmpty() {
  6. // 结果为空
  7. }

四、字段值数组

查询返回字段值数组本身类型为 []gdb.Value 类型,因此直接判断长度是否为 0 即可。

  1. // Array/FindArray
  2. r, err := g.Model("order").Fields("id").Where("status", 1).Array()
  3. if err != nil {
  4. return err
  5. }
  6. if len(r) == 0 {
  7. // 结果为空
  8. }

五、 Struct 对象(🔥注意🔥)

关于 Struct 转换对象来说 会有一点不一样,我们直接看例子吧。

当传递的对象 本身就是一个空指针时,如果查询到数据,那么会在内部 自动创建这个对象;如果没有查询到数据,那么这个空指针仍旧是一个空指针,内部并不会做任何处理。

  1. var user *User
  2. err := g.Model("order").Where("status", 1).Scan(&user)
  3. if err != nil {
  4. return err
  5. }
  6. if user == nil {
  7. // 结果为空
  8. }

当传递的对象 本身已经是一个初始化的对象,如果查询到数据,那么会在内部将数据赋值给这个对象; 如果没有查询到数据,那么此时就没办法将对象做 nil 判断空结果。因此 ORM 会返回一个 sql.ErrNoRows 错误,提醒开发者没有查询到任何数据并且对象没有做任何赋值,对象的所有属性还是给定的初始化数值,以便开发者可以做进一步的空结果判断。

  1. var user = new(User)
  2. err := g.Model("order").Where("status", 1).Scan(&user)
  3. if err != nil && err != sql.ErrNoRows {
  4. return err
  5. }
  6. if err == sql.ErrNoRows {
  7. // 结果为空
  8. }

ORM结果处理-为空判断 - 图1提示

所以我们推荐开发者不要传递一个初始化过后的对象给 ORM,而是直接传递一个对象的指针的指针类型( **struct 类型), ORM 内部会根据查询结果智能地做自动初始化。

六、 Struct 数组

当传递的对象数组本身是一个空数组(长度为 0),如果查询到数据,那么会在内部自动赋值给数组;如果没有查询到数据,那么这个空数组仍旧是一个空数组,内部并不会做任何处理。

  1. var users []*User
  2. err := g.Model("order").Where("status", 1).Scan(&users)
  3. if err != nil {
  4. return err
  5. }
  6. if len(users) == 0 {
  7. // 结果为空
  8. }

当传递的对象数组本身不是空数组,如果查询到数据,那么会在内部自动从索引 0 位置覆盖到数组上;如果没有查询到数据,那么此时就没办法将数组做长度为 0 判断空结果。因此 ORM 会返回一个 sql.ErrNoRows 错误,提醒开发者没有查询到任何数据并且数组没有做任何赋值,以便开发者可以做进一步的空结果判断。

  1. var users = make([]*User, 100)
  2. err := g.Model("order").Where("status", 1).Scan(&users)
  3. if err != nil {
  4. return err
  5. }
  6. if err == sql.ErrNoRows {
  7. // 结果为空
  8. }

ORM结果处理-为空判断 - 图2注意

由于 struct 转换利用了 Golang 反射特性,执行性能会有一定的损耗。如果您涉及到大量查询结果数据的 struct 数组对象转换,并且需要提高转换性能,请参考自定义实现对应 structUnmarshalValue 方法: 类型转换-UnmarshalValue