introduction
This article introduces an experience I like very much: the use of uncertain parameters (i.e.... operators) in GORM.
Getting started √——Junior level—Intermediate level—Advanced; this article is suitable for introduction and above.
Usage of uncertain parameters for GORM best practice
Undetermined parameters in Go
In Golang's language feature document, uncertain parameters (… parameters) are specifically explained. When an indefinite parameter is declared in the function definition…T
(for examplefunc Greeting(prefix string, who ...string)
), inside the function, it is equivalent to having a variable of type []T (for example,Greeting
In the function, there is a type[]string
ofwho
)。
If there is the following Greeting function:
func Greeting(prefix string, who ...string){ (prefix, len(who), who) if len(who) > 0 { Greeting(prefix, who[1:]...) } }
Then it can be passedGreeting("nobody")
andGreeting("hello:", "KiKi", "Joe", "Anna")
Come to callGreeting
method. For the usage of the former,who
The value ofnil
;For the latter usage,who
The value of[]string{"KiKi", "Joe", "Anna"}
。
Two points to note here:
1) You cannot directly pass in string slice callsGreeting("hello:", []string{"KiKi", "Joe", "Anna"})
, otherwise the compiler will report an error.
2) You can't call thisGreeting(prefix, who[1:])
, must be transmittedwho[1:]...
。
These two points can basically reveal the essence of uncertain parameters.It's more like declaring a computation process than a data type
① When used in a function declaration, what is done is to assemble the parameters passed in during function call into slices
② When parameters are transferred inside the function body, it means that the data in the slice is divided into a single element.. Well, that's basically it.
Best practices for uncertain parameters in GROM
To be honest, when you first get into uncertain parameters, you don’t feel the necessity of it; you rarely use it to write code on weekdays, and it feels like a toy or a gimmick of language.
Until recently, when using GROM, facing complex business logic, when there are more and more methods of customizing model layers, I always feel overwhelmed. It was not until I reviewed the code once, after the guidance of Teacher Lai of our group, that a new door was opened to my code world.
Let's look at a piece of code first:
// Topic topictype Topic struct { Title string `gorm:"index"` Content string `gorm:"type:text"` ViewCount int `json:"view_count"` ReplyCount int `json:"reply_count"` UserID int `gorm:"index" json:"user_id"` } // QueryByUserID Get topics based on UserIDfunc (t *Topic) QueryByUserID(userID int) (topics []Topic, err error) { db := ("user_id = ?", userID).Find(&topics).Error return }
In order to obtain the corresponding topic (Topic) based on the user ID (UserID), we have defined aQueryByUserID
The method of is deliberately passed a parameter here to express the meaning; it seems that this function can help us solve the separation between the model layer and the controller. However, if you really use it, you will find that this function actually has great limitations: it can only obtain all topics of a certain UserID, but it cannot realize further filtering of topics under this UserID (such as obtaining topics published in the past seven days).
So how should we define this Query function so that we are both elegant and powerful when using it?The answer is uncertain parameters。
Just imagine, weQueryByUserID
Functions are defined in the following way:
// QueryByUserID Get topics based on UserIDfunc (t *Topic) QueryByUserID(userID int, args ...interface{}) (topics []Topic, err error) { db := ("user_id = ?", userID) if len(args) >= 2 { db = (args[0], args[1:]...) } else if len(args) >= 1 { db = (args[0]) } err = (&topics).Error return }
We're hereQueryByUserID
Finally, an args indefinite parameter is added, thereby accepting the additional parameters passed in when the call is called. At the same time, in the function body, we apply it in different ways according to the length of the args, which is very elegantly extendedQueryByUserID
function. According to the characteristics of GORM, Go's reflection characteristics are used extensively. After checking the source code, you will know that this usage is completely feasible.
If an uncertain parameter is added, call it againQueryByUserID
When it comes to searching for topics more carefully, it is much more convenient. For example, if you want to obtain a topic with UserID of 1 and published in the last week, you can write it like this:
topics, err := (&Topic{}).QueryByUserID(1, "created_at > ?", ().Add(-7*24*) // ... Other treatments of topics and err
Very flexible, I like it very much!
summary
This article briefly introduces the uncertain parameters and GORM in Go, and describes the elegant combination of the two. A search for topics published by a user (Topic) introduces the great flexibility brought by adding uncertain parameters when using GORM.
Through such a combination, we can have a deeper understanding of uncertain parameters and GORM, and if we have a deeper understanding, we can develop it more easily.
For more information on the usage of GORM indefinite parameters, please follow my other related articles!