Gorm查询结果转为接口类型

huangapple go评论77阅读模式
英文:

Gorm Find result to interface

问题

我正在尝试使用Gorm为我的API构建一个通用的CrudRepository结构体。我知道泛型将在Go语言的第二个版本中引入,但我尝试使用反射或其他库来构建这个库。

在我的CrudRepository中:

func (repository *BaseRepository) find(result interface{}, pageSize int, page int) error {
  if page < 1 {
	return errors.ExceedsMinimumInt("page", "", 0, true, nil)
  }

  offset := (page - 1) * pageSize

  ent := reflect.Zero(reflect.TypeOf(result))

  repository.db = repository.db.Limit(pageSize).Offset(offset)
  err := repository.db.Find(&ent).Error

  result = ent

  if err != nil {
	return err
  }
  return nil
}

并且像这样调用这个方法:

func List(){
  var entityList []MyEntity
  find(entityList, 1, 10)
}

我认为,我不能将任何接口引用传递给**Gorm.db.Find()**方法。是否有其他方法可以成功实现?

英文:

I am trying to build a generic CrudRepository struct using Gorm for my api.
I know generics are coming to GoLang in version 2 but I try to build this lib using reflection or any other lib.

In my CrudRepository:

func (repository *BaseRepository) find(result interface{}, pageSize int, page int) error {
  if page &lt; 1 {
	return errors.ExceedsMinimumInt(&quot;page&quot;, &quot;&quot;, 0, true, nil)
  }

  offset := (page - 1) * pageSize

  ent := reflect.Zero(reflect.TypeOf(result))

  repository.db = repository.db.Limit(pageSize).Offset(offset)
  err := repository.db.Find(&amp;ent).Error

  result = ent

  if err != nil {
	return err
  }
  return nil
}

And calling this method sth like:

func List(){
  var entityList []MyEntity
  find(entityList, 1, 10)
}

I think, I cannot pass any interface reference into Gorm.db.Find() method
Is there any other way to succeed?

答案1

得分: 1

使用切片的指针作为自定义 find 方法的输入参数。

func (repository *BaseRepository) find(result interface{}, pageSize int, page int) error {
    if page < 1 {
        return errors.ExceedsMinimumInt("page", "", 0, true, nil)
    }

    if reflect.TypeOf(result).Kind() != reflect.Slice { // 检查 ❗️
        return errors.New("`result` 不是一个切片")
    }

    offset := (page - 1) * pageSize

    db = db.Limit(pageSize).Offset(offset)

    if err := db.Find(result).Error; err != nil {
        return err
    }
    return nil
}

用法 👇🏻

var entityList []MyEntity
err := find(&entityList, 10, 1)

此外,你还需要检查输入参数(result),因为 db.Find 不适用于查找单个结构体 👇🏻(检索单个对象

如果你想避免 ErrRecordNotFound 错误,可以使用类似 db.Limit(1).Find(&user) 的方式,Find 方法既接受结构体数据,也接受切片数据。

例如(Book 表为空):

b := Book{}
rowsAffectedQuantity := db.Find(&b).RowsAffected // 0
err = db.Find(&b).Error // nil
英文:

Use a pointer of a slice as input argument of custom find method.

func (repository *BaseRepository) find(result interface{}, pageSize int, page int) error {
    if page &lt; 1 {
      return errors.ExceedsMinimumInt(&quot;page&quot;, &quot;&quot;, 0, true, nil)
    }

    if reflect.TypeOf(result).Kind() != reflect.Slice { &#128072; check ❗️
		return errors.New(&quot;`result` is not a slice&quot;)
	}

	offset := (page - 1) * pageSize

	db = db.Limit(pageSize).Offset(offset)
	
	if err := db.Find(result).Error; err  != nil {
		return err
	}
	return nil
}

usage 👇🏻

var entityList []MyEntity
err := find(&amp;entityList, 10, 1)

Also you have to check input argument (result), because db.Find isn't fit to find single strut 👇🏻 (Retrieving a single object)

> If you want to avoid the ErrRecordNotFound error, you could use Find
> like db.Limit(1).Find(&user), the Find method accepts both struct and
> slice data

For example (Book table is empty):

b := Book{}
rowsAffectedQuantity := db.Find(&amp;b).RowsAffected // &#128072; 0
err = db.Find(&amp;b).Error // &#128072; nil

huangapple
  • 本文由 发表于 2021年9月25日 19:52:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/69325884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定