goshop开源项目的更新
> 备注:前面项目中用到的代码已经分享到GitHub中去了,并且以后所有项目中会出现的代码都会提交上去,欢迎查阅。感兴趣的可以点个star哦~
https://gitee.com/jobhandsome/goshop/
最近在研究微服务框架go-zero,没有更新,在这里说声抱歉,后面会持续更新新的功能。请继续关注~~~~
今天考虑参数绑定获取。这里肯定有些疑惑,之前不是封装了获取全部参数的方法吗?
回顾之前咱们封装了获取全部参数的方法,只能是`POST`请求,并且请求方式必须是:`application/x-www-form-urlencoded` 才能正常获取,局限性非常大。
* 需求1:使用任意请求方式,任意请求格式都可以获取到指定的值?
* 需求2:获取到的`struct`类型参数,转换成`map`类型用于`gorm`的`DB`查询?
#### 通过分析上面的两个需求得到几个结论:
* `gin`框架中可以使用参数绑定进行任意请求方式和请求类型获取请求的参数
* `gin`框架集成`gorm`,使用`DB.Where`条件查询时,需要传入`map`类型的数组格式,需要`struct转map`。
#### 既然知道要做什么了,那就开始:
首先,先使用绑定的方式获取参数:
```go
//1. 先定义一下传入的参数,这里使用form进行绑定,json进行别名
type ParamsRequest struct {
Page int64 `form:"page" binding:"required" json:"page"`
PageSize int64 `form:"pageSize" binding:"required" json:"pageSize"`
Name string `form:"name" json:"name"`
}
//2. 使用绑定来获取请求的参数 ctx => *gin.Context
var params ParamsRequest
if err := ctx.ShouldBind(¶ms); err != nil {
utils.Fail(ctx, "参数错误:"+err.Error(), nil)
return
}
```
获取到参数后,咱们就要使用参数进行`gorm`的`DB.Where`查询:
首先先对 `struct` 转换 `map`
```go
// 对应方法 AnyToMap interface 转 ma
func AnyToMap(v any) (map[string]any, error) {
dataJson, err := json.Marshal(v)
if err != nil {
return nil, err
}
var MapData map[string]any
err = json.Unmarshal(dataJson, &MapData)
if err != nil {
return nil, err
}
return MapData, nil
}
```
需要 过滤`page`和`pageSize`,不参与查询的
```go
ParamsFilter := utils.ParamsFilter("page,pageSize", paramsMap)
// 过滤指定数组中的key
func ParamsFilter(isFilterStr string, params map[string]any) map[string]any {
var data = make(map[string]any)
for key, value := range params {
if value != "" {
find := strings.Contains(isFilterStr, key)
if !find {
data[key] = value
}
}
}
return data
}
```
前面都是铺垫,现在才是重点,使用`gorm`进行数据查询
```go
// 获取 gorm 的 DB 句柄
DB := config.GetDB()
// 这里使用自己定义的模型就好
var Result []*model.Category
// 使用 Scopes 传入要分页的指针
resErr := DB.Scopes(Paginate.Paginate(strconv.FormatInt(params.Page, 10), strconv.FormatInt(params.PageSize, 10))).Where(ParamsFilter).Find(&Result).Error
// 查询的返回错误,如果有错误,就返回
if resErr != nil {
utils.Fail(ctx, resErr.Error(), nil)
return
}
// 对查询的 struct 数组转换 树结构 ToTree
var category model.Category
ResultLists := category.ToTree(Result)
utils.Success(ctx, "获取成功", ResultLists)
```
对应的`model`文件:
```go
type Category struct {
gorm.Model
Name string `form:"name" binding:"required" json:"name" gorm:"varchar(255);not null;default:'';comment:'分类名称'"` // 分类名称
Pid int64 `form:"pid" json:"pid" gorm:"size:11;not null;default:0;comment:'分类节点'"` // 分类节点:0根节点
Icon string `form:"icon" json:"icon" gorm:"varchar(255);not null;default:'';comment:'分类图标'"` // 分类图标
State int64 `form:"state" json:"state" gorm:"size:1;not null;default:0;comment:'分类状态:0未启用,1已启用'"` // 分类状态:0未启用,1已启用
Sort int64 `form:"sort" json:"sort" gorm:"size:11;not null;default:0;comment:'分类排序'"` // 分类排序
Tag string `form:"tag" json:"tag" gorm:"varchar(255);not null;default:0;comment:'分类标签'"` // 分类标签
Children *CategoryTrees `json:"children"`
}
// CategoryTrees 二叉树列表
type CategoryTrees []*Category
// ToTree 转换为树形结构
func (Category) ToTree(data CategoryTrees) CategoryTrees {
// 定义 HashMap 的变量,并初始化
TreeData := make(map[int64]*Category)
// 先重组数据:以数据的ID作为外层的key编号,以便下面进行子树的数据组合
for _, item := range data {
TreeData[int64(item.ID)] = item
}
// 定义 RoleTrees 结构体
var TreeDataList CategoryTrees
// 开始生成树形
for _, item := range TreeData {
// 如果没有根节点树,则为根节点
if item.Pid == 0 {
// 追加到 TreeDataList 结构体中
TreeDataList = append(TreeDataList, item)
// 跳过该次循环
continue
}
// 通过 上面的 TreeData HashMap的组合,进行判断是否存在根节点
// 如果存在根节点,则对应该节点进行处理
if pItem, ok := TreeData[item.Pid]; ok {
// 判断当次循环是否存在子节点,如果没有则作为子节点进行组合
if pItem.Children == nil {
// 写入子节点
children := CategoryTrees{item}
// 插入到 当次结构体的子节点字段中,以指针的方式
pItem.Children = &children
// 跳过当前循环
continue
}
// 以指针地址的形式进行追加到结构体中
*pItem.Children = append(*pItem.Children, item)
}
}
return TreeDataList
}
```
到了这一步,咱们就实现了上面需求的功能。 更多功能请持续关注!!!!!
#### 星球地址:https://t.zsxq.com/03MJM7YfI
#### **关注公众号「程序员小乔」**
![程序员小乔](https://www.qsjob.fun/zb_users/upload/2022/07/202207041451541741109.jpg "程序员小乔")
有疑问加站长微信联系(非本文作者))