学习gin框架知识的小注意点

Gin框架的初始化

有些项目中 初始化gin框架写的是: r := gin.New()

r.Use(logger.GinLogger(), logger.GinRecovery(true))

而不是r := gin.Default()

为什么呢?

点击进入Default源码发现其实他也是new+两个中间件,(Logger,Recovery)

default源码
func Default() *Engine {debugPrintWARNINGDefault()engine := New()engine.Use(Logger(), Recovery())return engine
}

但是中间件已经固定了,对于一些精细化开发来说换成new+自定义中间件则更有性价比;

自定义的:r := gin.New()r.Use(logger.GinLogger(), logger.GinRecovery(true)) //中间件
更精细化,这两个区别是一个用的是基础log,一个用的是gin框架特殊处理的log

项目结构

后端处理路线通常是先写router层:各种各样的路由信息,

再写controller层:

1 获取参数和参数校验 :定义参数结构,接收参数并存放
2 业务处理 :写到逻辑层
3 返回响应 :可以写中间件方便多次处理

然后logic层:(举登录的例子)

1.一系列登录逻辑判断:
用户是否存在         sql写在dao层,供logic层调用
账号密码是否符合格式  可以不使用sql语句的,直接逻辑判断
判断完成生成对应uid   调用一系列外置方法
对数据进行加密        调用一系列外置方法
保存进数据库          调用dao层sql方法

然后是dao层,写各种数据库操作封装成的方法以供调用

在我看来,controller层最大,logic以实现controller层的业务而出现,dao层最小,以实现logic层中的数据库操作为己任;

所以每次写小需求,先写router层,再写controller层,再写logic层,然后是dao层

这样理解起来比盲目学习要好很多;

Query和Param的区别

虽然已经学了不知道多少遍了,但这两个老是弄反,再写一遍吧

Query:

  • Query 用于获取 URL 查询参数。它从 URL 中解析参数,并返回一个字符串值。

如:

name := c.Query("name")https://example.com/search?query=golang&page=1&limit=10

Param:

  • Param 用于获取路径参数。路径参数是包含在 URL 中的参数,例如 /users/:id 中的 :id 就是路径参数。

如:

https://example.com/users/123
userID := c.Param("id") // Returns "123"

而shouldbindjson是什么呢?

ShouldBindJSON:

  • ShouldBindJSON 用于将 JSON 数据绑定到结构体。它从请求的 JSON 主体中提取数据,并将其解析到指定的结构体中。
var user User
if err := c.ShouldBindJSON(&user); err == nil {// 处理 user 结构体中的数据
}

将 HTTP 请求体中的 JSON 数据绑定到变量 user

注意点:ShouldBindJSON只能识别是不是json格式,并不能保证数据是否完全符合结构体格式,例如

image-20240125171059861

image-20240125171014484image-20240125171205274

这样写都会直接通过,

只有

image-20240125171143727

会报错,所以需要手动去对数据进行业务判断(数据校验),例如数据不为空,数据类型不对,数据不符合格式等等,因此就引入了第三方的validator库进行爽歪歪!(^ ▽ ^),ps:之后说这个库

image-20240125172035094

binding就是gin框架参数校验的tag:required就是不能为空,不然直接结束

常用tag

  1. form:
    • form:"fieldName" 表示该字段的值将从 HTTP 请求的表单数据中获取,其中 "fieldName" 是表单字段的名称。
  2. query:
    • query:"paramName" 表示该字段的值将从 URL 查询参数中获取,其中 "paramName" 是查询参数的名称。
  3. json:
    • json:"fieldName" 表示该字段的值将从 JSON 数据中获取,其中 "fieldName" 是 JSON 对象中的字段名。
  4. uri:
    • uri:"paramName" 表示该字段的值将从 URL 的路径参数中获取,其中 "paramName" 是路径参数的名称。
  5. binding:
    • binding:"required" 表示该字段是必需的,如果请求中缺少该字段,将返回错误。
  6. xml:
    • xml:"fieldName" 表示该字段的值将从 XML 数据中获取,其中 "fieldName" 是 XML 对象中的字段名。
  7. header:
    • header:"Header-Name" 表示该字段的值将从 HTTP 请求头中获取,其中 "Header-Name" 是请求头的名称。
  8. time:
    • time_format:"2006-01-02" 表示该时间字段的格式,用于将字符串转换为时间类型。

这些标签值用于告诉 Gin 框架在处理请求时如何从不同的数据源(如表单、查询参数、JSON 数据等)中提取和绑定数据。在使用 Gin 进行参数绑定时,可以根据请求中的数据类型和来源选择适当的标签。

接下来是重头戏validator库的说明,validator使用起来还是非常方便的,就是配置麻烦了一点(只是亿点点…)

image-20240125172606561

validator 提供了许多内置的验证规则,如 requiredminmaxemailurl 等,同时也支持使用正则表达式、自定义函数等进行验证。使用 validator 可以有效地提高应用程序的数据完整性和安全性。

而当不符合validator的tag规则时,返回的错误也是由validator库内置的,比如image-20240125172900409

我们需要将其改成中文并符合我们自己的代码习惯(这种配置配一次就行了,以后项目框架基本不会变,validator的代码也几乎不需要变化);

例如说自动翻译成中文,将特定字段格式转为json供前端使用,去掉结构体名称,处理复杂逻辑时候的结构体转换,咳咳,想要完美道阻且艰,错误信息完美到这里已经差不多了(还有很多优化空间阿伟!)

然后是固定代码格式:(只包含了初始化翻译器,可以自动翻译中文,把结构体字段转为json给前端看)

最后还是只有两个功能,可以直接使用哦~~

package controllerimport ("fmt""reflect""strings""github.com/gin-gonic/gin/binding""github.com/go-playground/locales/en""github.com/go-playground/locales/zh"ut "github.com/go-playground/universal-translator""github.com/go-playground/validator/v10"enTranslations "github.com/go-playground/validator/v10/translations/en"zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)// 这种初始化代码,知道意思就行,因为每次的项目这个都是提前写好的;
// 定义一个全局翻译器T
var trans ut.Translator// InitTrans 初始化翻译器
func InitTrans(locale string) (err error) {// 修改gin框架中的Validator引擎属性,实现自定制if v, ok := binding.Validator.Engine().(*validator.Validate); ok {// 注册一个获取json tag的自定义方法v.RegisterTagNameFunc(func(fld reflect.StructField) string {name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]if name == "-" {return ""}return name})zhT := zh.New() // 中文翻译器enT := en.New() // 英文翻译器// 第一个参数是备用(fallback)的语言环境// 后面的参数是应该支持的语言环境(支持多个)// uni := ut.New(zhT, zhT) 也是可以的uni := ut.New(enT, zhT, enT)// locale 通常取决于 http 请求头的 'Accept-Language'var ok bool// 也可以使用 uni.FindTranslator(...) 传入多个locale进行查找trans, ok = uni.GetTranslator(locale)if !ok {return fmt.Errorf("uni.GetTranslator(%s) failed", locale)}// 注册翻译器switch locale {case "en":err = enTranslations.RegisterDefaultTranslations(v, trans)case "zh":err = zhTranslations.RegisterDefaultTranslations(v, trans)default:err = zhTranslations.RegisterDefaultTranslations(v, trans)}return}return
}

使用的时候举例子:

controller/user的post登陆请求

func SignUpHandler(c *gin.Context) {//1 获取参数和参数校验p := new(models.ParamSignUp) //声明参数p是接收账号密码时的类型err := c.ShouldBindJSON(&p)  //获取参数传给pif err != nil {zap.L().Error("SignUp with invalid param", zap.Error(err)) //用日志输出//判断err是不是validator.ValidationErrors 类型,不是的话就不翻译了errs, ok := err.(validator.ValidationErrors)if !ok { //不是validator类型,正常响应c.JSON(http.StatusOK, gin.H{"msg": err.Error(),})}//是validator类型的,进行翻译操作c.JSON(http.StatusOK, gin.H{"msg": errs.Translate(trans),})return}

只用判断是不是validator类型,是的话返回err.Translate(trans)就好了

image-20240125205830430

image-20240125205840912

至于为什么不做其他的处理直到完美,首先代码复杂了,其次对效率也有不小的影响,有这两步已经差不多了;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/648154.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【并发编程】锁死的问题——如何解决?以及如何避免?

目录 1.如何解决 一、死锁的定义和原因 1.1 定义 1.2 原因 二、常见的死锁场景 2.1 线程间相互等待资源 2.2 嵌套锁的循环等待 2.3 对资源的有序请求 三、死锁排查的方法 3.1 使用jstack命令 3.2 使用jconsole 3.3 使用VisualVM 四、常见的解决方案 4.1 避免嵌套锁…

STK姿态分析(一)矢量组件

文章目录 内容简介一、卫星矢量二、卫星坐标平面三、卫星姿态球面 – 内容简介 接下来一系列文章将进行STK目标(卫星、导弹、火箭、飞机、船舶)姿态分析的仿真。本篇将使用矢量(vector)组件对卫星姿态、传感器指向等进行3D可视化…

注册表学习——注册表结构

简介:注册表是由很多项和值构成的。 HEKY_USERS(HKU) 主要保存默认用户及当前登录用户配置信息。 .DEFAULT 该项是针对未来创建的新用户所保存的默认配置项。 S-1-5-18等项 这些项叫作安全标识符(SID)用来表示Windows操…

Linux(linux版本 centos 7) 下安装 oracle 19c详细教程(新手小白易上手)

一、安装前准备 1、下载预安装包 wget http://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm预安装包下载成功 2、下载oracle安装包 下载地址如下 https://www.oracle.com/cn/database/technologies…

渲染与创造之美:互为表里的艺术

在五彩斑斓的艺术世界中,渲染与创造是两股不可或缺的力量。它们之间的关系,恰如弓与箭,互为表里,共同塑造出无数令人叹为观止的视觉景象。创造之美是指通过创新思维和创造力,将想象具象化为现实,创造出新的…

引领未来:云原生在产品、架构与商业模式中的创新与应用

文章目录 一、云原生产品创新二、云原生架构设计三、云原生商业模式变革《云原生落地 产品、架构与商业模式》适读人群编辑推荐内容简介目录 随着云计算技术的不断发展,云原生已经成为企业数字化转型的重要方向。接下来将从产品、架构和商业模式三个方面&#xff0c…

最小覆盖子串(Leetcode76)

例题: 分析: 比如现在有字符串(s),s "ADOBECODEBANC", 给出目标字符串 t "ABC", 题目就是要从原始字符串(s)中找到一个子串(res)可以覆盖目标字符串 t &…

微信小程序(十六)slot插槽

注释很详细&#xff0c;直接上代码 上一篇 温馨提醒&#xff1a;此篇需要自定义组件的基础&#xff0c;如果不清楚请先看上一篇 新增内容&#xff1a; 1.单个插槽 2.多个插槽 单个插糟 源码&#xff1a; myNav.wxml <view class"navigationBar custom-class">…

师如灯塔,照我前行:我在誉天的RHCA认证之旅

时光荏苒&#xff0c;岁月如梭。2022年10月&#xff0c;我踏上了通向RHCA&#xff08;Red Hat Certified Architect&#xff09;证书的征程。2023年11月&#xff0c;我成功拿到了RHCA证书&#xff0c;也给这段旅程画上了圆满的句号。 而在这充满挑战和成长的旅程中&#xff0c;…

防火墙ip配置

如图所示需要配置该拓扑的ip 1.首先在交换机7上创建vlan 2 3 [Huanwei]vlan batch 2 3 2.分别进入0/0/3 和0/0/2接口 [Huawei-GigabitEthernet0/0/3]port link-type access [Huawei-GigabitEthernet0/0/2]port link-type access 3.定义所属vlan [Huawei-GigabitEthernet0…

【python爬虫】爬虫编程技术的解密与实战

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a; 爬虫】网络爬虫探秘⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1f33c;实验目的 &#x1f…

数字孪生系统的难点

数字孪生系统的开发和实施涉及一些技术难点&#xff0c;这些难点需要综合应用多个领域的知识和技术来克服。以下是一些数字孪生系统开发中的技术难点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1…

【每日一题】4.LeetCode——杨辉三角

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢迎各位大佬指点&…

监听元素宽高变化---new ResizeObserver

参考&#xff1a;ResizeObserver API详解-CSDN博客 有的时候需要监听某个元素的宽高变化&#xff0c;这个时候可以使用JS的 resizeObserver 钩子函数。 用于监视元素的大小变化。它可以观察一个或多个 DOM 元素&#xff0c;以便在元素的大小或形状发生变化时触发回调函数。R…

安全用电管理平台方案介绍——Acrelcloud-6000

安全用电管理平台是一个针对电力系统安全管理的平台&#xff0c;旨在提供对电力设备和用电行为进行监控、分析和管理的解决方案。该平台结合了物联网技术、数据分析和远程监控等技术手段&#xff0c;能够实时监测、分析和预警电力系统的安全状况&#xff0c;以便及时采取措施防…

广州工业元宇宙赋能新型工业化,推动工业制造业数字化转型发展

随着科技的飞速发展&#xff0c;新型工业化的概念逐渐成为全球关注的焦点。在数字化转型的浪潮中&#xff0c;工业制造业的发展面临着巨大的机遇和挑战。广州作为中国南方的重要工业基地&#xff0c;积极探索工业元宇宙的赋能作用&#xff0c;以推动工业制造业的数字化转型发展…

[蓝桥学习] 前缀和与差分

前缀和原理 特点 求区间和 如果要实现一边修改一边查询&#xff0c;需要使用树状树组和线段树。 例题 题目很简单&#xff0c;但是代码实现惊艳到我了&#xff0c;是L就加1&#xff0c;是Q就减1&#xff0c;如果区间 [i,j] 是平衡子串的话&#xff0c;那它会在前缀prefix i …

基于Kubernetes(K8s)构建企业容器云基础运行环境

cncfstack 新 文章上线&#xff1a; 书名&#xff1a;《云原生解决方案》 地址&#xff1a;https://zhaowenyu.com/cncf-solution 访问&#xff1a;文章底部“阅读原文”或访问域名 云原生计算是云计算发展新的里程碑阶段&#xff0c;是当今与未来很长一段时间中 IT 发展的技…

【学网攻】 第(10)节 -- 路由器单臂路由配置

系列文章目录 目录 系列文章目录 文章目录 前言 一、单臂路由是什么&#xff1f; 二、实验 1.引入 实验拓扑图 PC配置 Sw配置 Router配置 实验验证 总结 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识及使用【学网攻】 第(3)节 -- 交…

【医学图像隐私保护】PLAN方法:解决 GAN 生成医学图像 Latent 空间中的隐私保护

PLAN方法&#xff1a;解决 GAN 生成医学图像 Latent 空间中的隐私保护方法 PLAN 原理StyleGAN 生成视网膜图k-SALSA 生成视网膜图PLAN方法 生成视网膜图 总结 PLAN 原理 论文&#xff1a;https://arxiv.org/abs/2307.02984 代码&#xff1a;https://github.com/perceivelab/P…