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
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(...)
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
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
Complementing @R3v4n answer:
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(...)
}