Go项目实战—参数绑定,类型转换

qiaoshuai951123 · · 1597 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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(&params); 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 "程序员小乔")

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1597 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传