如何在函数中修改 GORM 数据库指针?

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

How to modify GORM DB pointer in function?

问题

我有一个用Go编写的REST API应用程序,它使用GORM作为ORM。在重构某些部分时,我想将一些常见操作移动到一个外部函数ApplyToDBQuery(query *gorm.DB)中,该函数接受一个指向DB查询的指针并对其进行修改,以便稍后可以使用修改后的查询。

示例用法:

query = shared.DB.Debug()
req.ApplytoDBQuery(query)
if query.find(&data).Error != nil {...}

func (this *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) {
    query.Limit(...)
    query.Offset(...)
    query.Where(...)
}

我认为,由于我传递了一个指针给函数,原始查询应该已经被修改了,但实际上原始查询并没有发生任何变化。

我还尝试过传递指向指针的指针ApplyToDBQuery(query **gorm.DB),返回修改后的指针ApplyToDBQuery(query *gorm.DB) *gorm.DB,甚至是这两者的组合 - ApplyToDBQuery(query **gorm.DB) *gorm.DB,但由于想法不足,都没有成功。

英文:

I have a REST API application written in Go, which uses GORM as ORM. During refactoring of some parts, I wanted to move some common operations to an external function ApplyToDBQuery(query *gorm.DB), which takes a pointer to the DB query and modifies it, so that the modified query can be used later.

Example usage:

query = shared.DB.Debug()
req.ApplytoDBQuery(query)
if query.find(&data).Error != nil {...}

func (this *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) {
    query.Limit(...)
    query.Offset(...)
    query.Where(...)
}

I thought, that since I'm passing a pointer to the function, the original query should've been modified, but nothing really happened to the original query.

I've also tried passing a pointer to pointer ApplyToDBQuery(query **gorm.DB), returning the modified pointer ApplyToDBQuery(query *gorm.DB) *gorm.DB and out of lack of ideas, even a combination of these two - ApplyToDBQuery(query **gorm.DB) *gorm.DB

答案1

得分: 2

Gorm对象在每次操作时都会克隆自身,因此原始指向的值永远不会改变。

你应该返回最新版本的gorm.DB:

return query.Limit(...).Offset(...).Where(...)
英文:

Gorm object clone itself for every operation, therefore the original pointed value is never changed.

You should return the latest version of gorm.DB:

return query.Limit(...).Offset(...).Where(...)

答案2

得分: 1

将方法接收器更改为:

func (this *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) *gorm.DB {
	return query.Limit(...).
		Offset(...).
		Where(...)
}

然后将其用作:

query = req.ApplytoDBQuery(query)
if query.find(&data).Error != nil {...}

原因已经由 @R3v4n 指出。

英文:

Change the method receiver to

func (this *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) *gorm.DB {
	return query.Limit(...).
		Offset(...).
		Where(...)
}

then use it as:

query = req.ApplytoDBQuery(query)
if query.find(&data).Error != nil {...}

The reason is already pointed by @R3v4n

答案3

得分: 1

你应该按照前两个答案的建议去做,但是如果由于某种原因,你必须对传入的指针进行更改,你仍然可以通过"手动"的方式来实现。

query = shared.DB.Debug()
req.ApplytoDBQuery(query)
if query.find(&data).Error != nil {...}

func (r *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) {
    q := query.Limit(...).Offset(...).Where(...)
    *query = *q
}

另外,一点注意事项是,通常不建议使用thisself这样的接收者名称,而是更倾向于使用类型名称的简短缩写,比如使用1到3个字母。

例如:

func (r *Request) AddCookie(c *Cookie)
func (c *Client) Get(url string) (resp *Response, err error)
func (srv *Server) ListenAndServe() error
英文:

You should go with what the previous two answers recommend, but, if for some reason, you have to apply changes to the passed in pointer, you can still do it "manually".

query = shared.DB.Debug()
req.ApplytoDBQuery(query)
if query.find(&data).Error != nil {...}

func (r *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) {
    q := query.Limit(...).Offset(...).Where(...)
    *query = *q
}

As a side note, it is generally discouraged to use receiver names like this and self, instead the preferred way is to use a short, let's say 1 to 3 letters, abbreviation of the type's name.

For example:

func (r *Request) AddCookie(c *Cookie)
func (c *Client) Get(url string) (resp *Response, err error)
func (srv *Server) ListenAndServe() error

答案4

得分: 0

补充 @R3v4n 的回答:

  1. 使用链式调用
  2. 使用 db.Scopes 来重用代码,而不是常规的函数调用。

可以像这样:

query = shared.DB.Debug()
if query.Scopes(req.ApplyToDBQuery).find(&data).Error != nil {
  // 处理错误
}

func (this *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) *gorm.DB {
    return query.Where(...).Limit(...).Offset(...)
}
英文:

Complementing @R3v4n answer:

  1. Use chaining
  2. Use db.Scopes for code reusage instead of usual func calls.

It can be like this:

query = shared.DB.Debug()
if query.Scopes(req.ApplyToDBQuery).find(&data).Error != nil {
  // handle error
}

func (this *MyCustomRequest) ApplyToDBQuery(query *gorm.DB) *gorm.DB {
    return query.Where(...).Limit(...).Offset(...)
}

huangapple
  • 本文由 发表于 2017年9月8日 07:32:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/46106522.html
匿名

发表评论

匿名网友

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

确定