introduction
What I want to learn today isUse of functions. The function of this function is to reuse query conditions.
What is gorm Scopes
In the project, you will definitely encounter many query conditions that need to be reused. For example, commonly used scenarios include paging, determining data permissions during querying, etc.
For example, we have two data resources: user list and department list. Then, pagination will be involved when querying the list. Of course, you can add the query related to the above list to each list. At the same time, you can also extract the paged query and make it into a public function.
So how can the extracted paging conditions be reused in each list? That's usefunction.
Let's first look at a simple example of using functions. This example is just for illustrationUse of functions. as follows:
func AmountGreaterThan1000(db *) * { return ("amount > ?", 1000) } func PaidWithCreditCard(db *) * { return ("pay_mode_sign = ?", "C") } func PaidWithCod(db *) * { return ("pay_mode_sign = ?", "C") } func OrderStatus(status []string) func (db *) * { return func (db *) * { return ("status IN (?)", status) } } // Find all credit card orders with a total amount of more than 1000(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders) // Find all COD orders with an amount greater than 1000(AmountGreaterThan1000, PaidWithCod).Find(&orders) // Find all paid or shipped orders with an amount greater than 1000(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
From the above example, we can see that the first 4 functions arefunc (db *) *
A function of type, that is, input a db and then return a db. Business logic in this function is actually the most common、
Just commonly used query condition statements. It's just that this public query statement is extracted and reused.
Then pass this function toScopes
。Scopes
Functions are simplyfunc (db *) *
Put it inIn this slice.
Finally, when the final execution is performed, it will be looped throughSlice, execute each of the slices in turn
func (db *) *
function. In this way, the extracted public query conditions are fused together.
Use scenario 1 -- Pagination
Of course, the most common thing we use when querying is the pagination function. So, how to use itImplement the reuse of paging query. as follows:
func Paginate(r *) func(db *) * { return func (db *) * { q := () page, _ := (("page")) if page <= 0 { page = 1 } pageSize, _ := (("page_size")) switch { case pageSize > 100: pageSize = 100 case pageSize <= 0: pageSize = 10 } offset := (page - 1) * pageSize return (offset).Limit(pageSize) } } (Paginate(r)).Find(&users) (Paginate(r)).Find(&articles)
You see, I first define a paginated functionPaginate
function, which receives a*
parameter, then return afunc(db *) *
function. becauseFunctions only accept
func(db *) *
Function of type. Finally,Paginate
Passing the function toScopes
Just function.
Usage Scenario 2 -- Data Permissions
In the go-admin open source project, we also found a typical application, which is data permissions. In our system, we will encounter such scenarios: some data can only be viewed or operated by yourself; or your superiors can also view or operate; or personnel from the same department can view or operate the data of their own department, but cannot view or operate the permissions of other departments; or they can only view the data of the same department but cannot operate the data of the same department, etc.
In go-admin, it is usedFunctions to use permission query conditions uniformly. In each operation,
Scopes
A function passed inPermission
function.Permissioin
Functions are converted into corresponding SQL statements based on the permissions owned by different roles. as follows:
// DeleteAction General Delete Actionfunc DeleteAction(control ) { return func(c *) { db, err := (c) ...//Omitted some logic //Data permission check p := GetPermissionFromContext(c) // Pass the Permission function into the Scopes function db = (c).Scopes( Permission((), p), ).Where(()).Delete(object) ...//Omitted some logic // Check the number of rows of the operation. If the number of rows of the operation is 0, it means there is no permission. if == 0 { (c, , nil, "No permission to delete this data") return } (c, (), "Delete successfully") () } } // Logic of Permission function// Enumerate values according to different data ranges, convert them to different Where conditionsfunc Permission(tableName string, p *DataPermission) func(db *) * { return func(db *) * { if ! { return db } switch { case "2": return (tableName+".create_by in (select sys_user.user_id from sys_role_dept left join sys_user on sys_user.dept_id=sys_role_dept.dept_id where sys_role_dept.role_id = ?)", ) case "3": return (tableName+".create_by in (SELECT user_id from sys_user where dept_id = ? )", ) case "4": return (tableName+".create_by in (SELECT user_id from sys_user where sys_user.dept_id in(select dept_id from sys_dept where dept_path like ? ))", "%/"+()+"/%") case "5": return (tableName+".create_by = ?", ) default: return db } } }
Summarize
gorm Scopes is a very powerful feature that allows you to reuse your logic and implement more complex query logic when querying. When using gorm Scope, you need to define a Scope function and apply it when querying. The Scope function can be called chained and can receive parameters. Learning and mastering this feature will make you achieve twice the result with half the effort when writing gorm queries.
The above is the detailed content of the example of using functions to implement multiplexed query logic. For more information about multiplexed query logic, please pay attention to my other related articles!