gin框架提高篇(四)

news2025/1/13 8:00:54

参数校验(一)

uuid包:https://github.com/satori/go.uuid
因为作者更改了参数限制,导致会出问题 → 问题解决

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	uuid "github.com/gofrs/uuid"
	"net/http"
	"unicode/utf8"
)

type UserInfo struct {
	Id   string `validate:"uuid" json:"id"`           // UUID 类型
	Name string `validate:"checkName" json:"name"`    // 自定义校验
	Age  uint8  `validate:"min=0,max=130" json:"age"` // 大于0小于130
}

var validate *validator.Validate

// 校验初始化
func init() {
	validate = validator.New()                              // 初始化校验示例
	validate.RegisterValidation("checkName", checkNameFunc) // 自定义校验方法
}

func checkNameFunc(fl validator.FieldLevel) bool {
	count := utf8.RuneCountInString(fl.Field().String()) // 获取 Name 的字符串表示,并计算 Unicode 字符的数量
	if count >= 2 && count <= 12 {
		return true
	}
	return false
}

func main() {
	uuid.Must(uuid.NewV4()) // 由 uuid包 生成 uuid

	r := gin.Default()
	var user UserInfo
	r.POST("/validate", func(context *gin.Context) {
		err := context.Bind(&user)
		if err != nil {
			context.JSON(http.StatusBadRequest, "请求参数错误")
			return
		}
		err = validate.Struct(user)
		if err != nil {
			for _, e := range err.(validator.ValidationErrors) {
				fmt.Println("错误的字段:", e.Field())
				fmt.Println("错误的值:", e.Value())
				fmt.Println("错误的tag:", e.Tag())
			}
			context.JSON(http.StatusBadRequest, "数据校验失败")
			return
		}
		context.JSON(http.StatusOK, "数据校验成功")
	})
	r.Run(":9090")
}

在这里插入图片描述

参数校验(二)

validator包:https://github.com/go-playground/validator

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"net/http"
)

type ValUser struct {
	Name  string `validate:"required" json:"name"`
	Age   uint8  `validate:"gte=0,lte=130" json:"age"`
	Email string `validate:"required,email" json:"email"`
	// 切片数据类型
	Address []ValAddress `validate:"dive" json:"address"`
}

type ValAddress struct {
	Province string `validate:"required" json:"province"`
	City     string `validate:"required" json:"city"`
	Phone    string `validate:"numeric,len=11" json:"phone"`
}

var validate *validator.Validate

func init() {
	validate = validator.New() // 初始化
}

func main() {
	r := gin.Default()
	var user ValUser
	r.POST("/validate", func(context *gin.Context) {
		//testData(context)

		err := context.Bind(&user)
		if err != nil {
			context.JSON(http.StatusBadRequest, "参数错误,绑定失败")
			return
		}
		// 参数校验
		if validateUser(user) {
			context.JSON(http.StatusOK, "数据校验成功")
			return
		}
		context.JSON(http.StatusBadRequest, "校验失败")
		return
	})
	r.Run(":9090")
}

//func testData(context *gin.Context) {
//	address := ValAddress{
//		Province: "浙江省",
//		City:     "杭州市",
//		Phone:    "13575121689",
//	}
//	user := ValUser{
//		Name:    "张三",
//		Age:     15,
//		Email:   "1993036922@qq.com",
//		Address: []ValAddress{address},
//	}
//	context.JSON(http.StatusOK, user)
//}

func validateUser(u ValUser) bool {
	err := validate.Struct(u)
	if err != nil {
		for _, e := range err.(validator.ValidationErrors) {
			fmt.Println("错误的字段:", e.Field())
			fmt.Println("错误的值:", e.Value())
			fmt.Println("错误的tag:", e.Tag())
		}
		return false
	}
	return true
}

在这里插入图片描述

swagger

swagger地址:https://github.com/swaggo/gin-swagger

引入步骤

  • 下载swag及相关包
    • go get -u github.com/swaggo/swag/cmd/swag
    • go get -u github.com/swaggo/gin-swagger
    • go get -u github.com/swaggo/files
  • 实现 Api 代码
  • 编写注释:参考https://github.com/swaggo/swag/blob/master/README.md#declarative-comments-format
  • 在代码中使用 swagger 中间件
  • 引入docs:如我的引入为 _ “2-golang/docs”,_ 表示不为包赋名
  • 执行终端命令:swag init

如果出现 swag 不是命令,无法识别,则先执行: go install github.com/swaggo/swag/cmd/swag@latest

ps:文件名必须叫 main

package main

import (
	_ "2-golang/docs"
	"fmt"
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"net/http"
)

type User struct {
	UserName string `json:"user_name"`
	Password string `json:"password"`
}

type Response struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
	Data string `json:"data"`
}

func main() {
	r := gin.Default()
	// 使用 swagger 中间件
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	r.GET("/login", login)

	r.POST("/register", register)

	r.Run(":9090")
}

// @Tags 注册接口
// @Summary 注册
// @Description register
// @Accept json
// @Produce json
// @Param username formData string true "用户名"
// @Param password formData string true "密码"
// @Success 200 {string} json "{"code": 200, "data":"{"name":"username","password":"password"}","msg":"OK"}"
// @Router /register [post]
func register(context *gin.Context) {
	var user User
	// get 使用的是 query,post 使用的是 formData,而 Bind 只能绑定 query
	// err := context.Bind(&user)
	err := context.BindQuery(&user)

	if err != nil {
		context.JSON(http.StatusBadRequest, "数据错误")
		return
	}

	res := Response{
		Code: http.StatusOK,
		Msg:  "注册成功",
		Data: "OK",
	}

	context.JSON(http.StatusOK, res)
}

// @Tags 登录接口
// @Summary 登录
// @Description login
// @Accept json
// @Produce json
// @Param username query string true "用户名"
// @Param password query string false "密码"
// @Success 200 {string} json "{"code": 200, "data":"{"name":"username","password":"password"}","msg":"OK"}"
// @Router /login [get]
func login(context *gin.Context) {
	userName := context.Query("name")
	pwd := context.Query("pwd")

	fmt.Println(userName, pwd)

	res := Response{}
	res.Code = http.StatusOK
	res.Msg = "登陆成功"
	res.Data = "OK"

	context.JSON(http.StatusOK, res)
}

在这里插入图片描述

gin框架cookie

package main

import (
	"encoding/hex"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

var cookieName string
var cookieValue string

func main() {
	r := gin.Default()

	r.Use(cookieAuth())

	r.GET("/cookie", func(context *gin.Context) {
		name := context.Query("name")

		if len(name) <= 0 {
			context.JSON(http.StatusOK, "数据错误")
			return
		}

		cookieName = "cookie_" + name
		cookieValue = hex.EncodeToString([]byte(cookieName + "value"))
		val, _ := context.Cookie(cookieName)

		if val == "" {
			context.String(http.StatusOK, "Cookie已经下发,下次登录有效", cookieName)
			return
		}
		context.String(http.StatusOK, "验证成功,cookie值为:%s", val)
	})

	r.Run(":9090")
}

func cookieAuth() gin.HandlerFunc {
	return func(context *gin.Context) {
		val, _ := context.Cookie(cookieName)

		if val == "" {
			context.SetCookie(cookieName, cookieValue, 3600, "/", "localhost", true, true)
			fmt.Println("cookie已经保存完成!")
		}
	}
}

在这里插入图片描述

gin框架session

package main

import (
	"net/http"

	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()

	// 加入 session 中间件
	store := cookie.NewStore([]byte("session_secret")) // 创建基于cookie的session存储
	r.Use(sessions.Sessions("mySession", store))       // 使用session中间件,并指定session名称和存储方式

	r.GET("/session", func(context *gin.Context) {
		name := context.Query("name")
		if len(name) <= 0 {
			context.JSON(http.StatusOK, "数据错误")
			return
		}

		sessionName := "session_" + name        // 构造session名称
		sessionValue := "session_value_" + name // 构造session值

		session := sessions.Default(context) // 获取默认的session实例
		sessionData := session.Get(sessionName)

		if sessionData != sessionValue { // 如果session中不存在对应值,则为首次访问
			session.Set(sessionName, sessionValue) // 设置 session
			session.Save()                         // 保存 session

			context.JSON(http.StatusOK, "首次访问,session已保存:"+sessionValue)
			return
		}
		context.JSON(http.StatusOK, "访问成功,您的session是:"+sessionData.(string))
	})

	r.Run(":9090") // 启动HTTP服务器,监听9090端口
}

gin框架Https

  • 申请证书并下载证书:https://keymanager.org/
    在这里插入图片描述

在这里插入图片描述

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/unrolled/secure"
	"net/http"
)

// HttpRes 结构体用于定义HTTP响应格式
type HttpRes struct {
	Code   int    `json:"code"`   // 响应状态码
	Result string `json:"result"` // 响应结果消息
}

func main() {
	r := gin.Default() // 创建默认的gin路由引擎

	// 使用HTTPS处理程序中间件
	r.Use(httpsHandler())

	// 定义GET路由"/https_test"
	r.GET("/https_test", func(context *gin.Context) {
		// 返回JSON格式的成功消息
		context.JSON(http.StatusOK, HttpRes{
			Code:   http.StatusOK,
			Result: "测试成功",
		})
	})

	path := "D:/2-golang/CA/"                       // 证书路径
	r.RunTLS(":9090", path+"ca.crt", path+"ca.key") // 使用TLS在9090端口运行服务器
}

// httpsHandler 返回一个处理HTTPS请求的中间件函数
func httpsHandler() gin.HandlerFunc {
	return func(context *gin.Context) {
		// 创建secure中间件实例
		secureMiddleware := secure.New(secure.Options{
			SSLRedirect:          true, // 强制SSL重定向
			STSSeconds:           1536000,
			STSIncludeSubdomains: true,
			STSPreload:           true,
			FrameDeny:            true,
			ContentTypeNosniff:   true,
			BrowserXssFilter:     true,
		})
		// 处理HTTPS请求
		err := secureMiddleware.Process(context.Writer, context.Request)
		if err != nil {
			// 如果出现错误,返回数据不安全的响应
			context.AbortWithStatusJSON(http.StatusBadRequest, "数据不安全")
			return
		}
		if status := context.Writer.Status(); status > 300 && status < 399 {
			// 如果响应状态码是重定向类型,则终止请求
			context.Abort()
			return
		}
		context.Next() // 继续处理下一个中间件或路由处理函数
	}
}

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

STL容器搜索:当直接访问STL容器时,如何执行有效和正确的搜索?

在访问STL容器时进行搜索 一、简介二、std::vector, std::deque, std::list三、std::map, std::multimap, std::set, std::multiset四、std::string六、总结 一、简介 本文主要了解如何在直接访问c容器时高效地进行搜索。在STL容器中搜索&#xff0c;要牢记一个原则&#xff1…

禾赛面经分享

前言 禾赛的linux开发工程师&#xff08;实习&#xff09;&#xff0c;base是上海&#xff0c;以下是面试遇到的一些问题。 目录 前言题目与答案C语言部分嵌入式相关手撕题 题目与答案 C语言部分 static关键字的作用 static修饰局部变量时&#xff1a;①改变了其存储位置&…

基础知识集合

https://blog.csdn.net/sheng_q/category_10901984.html?spm1001.2014.3001.5482 epoll 事件驱动的I/O模型&#xff0c;同时处理大量的文件描述符 内核与用户空间共享一个事件表&#xff1a;监控的文件描述符以它们的状态&#xff0c;当状态变化&#xff0c;内核将事件通知给…

【分治】Leetcode 库存管理 III

题目讲解 LCR 159. 库存管理 III 本题的含义就是让求出最小的k个数 算法讲解 class Solution { public:void my_qsort(vector<int>& nums, int l, int r){if(l > r) return ;int i l, left l-1, right r1;int key nums[rand() % (r - l 1) l];//完成分三…

大数据真题讲解系列——拼多多数据分析面试题

拼多多数据分析面试题&#xff1a;连续3次为球队得分的球员名单 问题&#xff1a; 两支篮球队进行了激烈的比赛&#xff0c;比分交替上升。比赛结束后&#xff0c;你有一个两队分数的明细表&#xff08;名称为“分数表”&#xff09;。表中记录了球队、球员号码、球员姓名、得…

hv第一坑:定时器

错误代码 重试策略&#xff1a;一次延迟1s,最长30s直至事件成功。 int try_count 0;//do something if(not success)m_loop->setTimerInLoop((try_count > 30 ? 30: try_count) *1000 , cb, INFINITE, 0x100);表现现象 cpu 爆了内存爆了 总结原因 hv内部代码bug&…

Maven通过flatten-maven-plugin插件实现多模块版本统一管理

正文 起因是公司开始推代码版本管理的相关制度&#xff0c;而开发过程中经常使用多模块构建项目&#xff0c;每次做版本管理时都需要对每个模块及子模块下的pom文件中parent.version和模块下依赖中的version进行修改&#xff0c;改的地方非常多&#xff0c;且非常容易漏。为此…

如何用Python构建一个生产级别的电影推荐系统 - 机器学习手册

构建项目是彻底学习概念并发展必要技能的最有效方式之一。 项目使您沉浸在现实世界的问题解决中&#xff0c;巩固您的知识&#xff0c;并培养批判性思维、适应能力和项目管理专业知识。 本指南将带您逐步构建一个根据用户喜好量身定制的电影推荐系统。我们将利用一个庞大的包…

20240419,继承,多态

土豆的老家陕西安康&#xff01;怪舒服的咯&#xff0c;广西一眼望去全是房子啦&#xff0c;小时候一眼开敞水田再也回不来啦 目录 五&#xff0c;继承 5.1 基本语法 5.2 继承方式 5.3 继承中的对象模型 5.4 构造和析构顺序 5.5 同名成员处理 5.6 同名静态成员处理 5.…

c#+unity基础

序列化&#xff1a; [SerializeField]&#xff0c;点不出来&#xff0c;只能在面板上显示绑定游戏物体 //公有隐藏 特有函数 特有函数&#xff1a;不需要调用&#xff0c;自动执行 Awake最先执行->OnEable 面向对象思想 面向对象思想&#xff1a;分为具体对象和抽象对…

从预训练损失的角度,理解语言模型的涌现能力

原文&#xff1a;Understanding Emergent Abilities of Language Models from the Loss Perspective 摘要 本文从预训练损失的角度重新审视语言模型的涌现能力&#xff0c;挑战了以往以模型大小或训练计算量为标准的观念。通过实验&#xff0c;作者发现预训练损失是预测下游任…

【算法】合并两个有序链表

本题来源---《合并两个有序链表》 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] /*** Definition for singl…

JavaSE——常用API进阶二(6/8)-ZoneId、ZoneDateTime、Instant(常见方法、用法示例)

目录 ZoneId 常见方法 用法示例 ZoneDateTime 常见方法 用法示例 Instant 常见方法 用法示例 如果在开发中我们有这样的需求&#xff1a;我们的系统需要获取美国现在的时间&#xff0c;或者其他地区的时间给用户观看&#xff0c;或者进行一些处理&#xff0c;那应该怎…

循环开关定时器(Smart PLC梯形图代码)

很多设备不需要复杂的逻辑时序控制,只需要实现简单的循环定时开关功能,对于这样的控制我们可以利用定时器组合去实现,但是如果系统里需要循环定时控制的设备比较多,那我们建议大家编写一个这样的循环定时开关功能块,SMART PLC循环开关定时器还可以参考下面文章链接 1、周…

短视频批量采集提取软件|视频关键词下载工具

短视频批量采集软件&#xff1a;快速抓取、高效下载 一、开发背景 随着短视频平台的兴起&#xff0c;获取并分析相关视频内容已成为许多业务的必要步骤。然而&#xff0c;传统的手动方式无法满足快速、批量获取的需求&#xff0c;因此我们开发了一款专业的短视频批量采集软件。…

FreeRTOS时间管理

FreeRTOS时间管理 主要要了解延时函数&#xff1a; 相对延时&#xff1a;指每次延时都是从执行函数vTaskDelay()开始&#xff0c;直到延时指定的时间结束。 绝对延时&#xff1a;指将整个任务的运行周期看成一个整体&#xff0c;适用于需要按照一定频率运行的任务。 函数 vTa…

springcloud第4季 springcloud-alibaba之sentinel

一 sentinel介绍 1.1 sentinel作用 sentinel是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障服务的稳定性。 1.2 组成部分 sen…

A Geolocation Databases Study(2011年)第五部分:Evalution Model

下载地址:A Geolocation Databases Study | IEEE Journals & Magazine | IEEE Xplore 被引次数:195 Shavitt Y, Zilberman N. A geolocation databases study[J]. IEEE Journal on Selected Areas in Communications, 2011, 29(10): 2044-2056. 5. Discussion 在我们讨…

Jenkins的安装和部署

文章目录 概述Jenkins部署项目的流程jenkins的安装启动创建容器进入容器浏览器访问8085端口 Jenkins创建项目创建example项目 概述 Jenkins&#xff1a;是一个开源的、提供友好操作界面的持续集成&#xff08;CLI&#xff09;工具&#xff0c;主要用于持续、自动构建的一些定时…

什么是知乎知+广告推广?

知乎作为中国领先的知识分享社区和高质量用户群体汇聚地&#xff0c;其广告价值日益凸显&#xff0c;其中&#xff0c;“知”作为知乎官方推出的创新广告形式&#xff0c;正逐渐成为品牌与消费者深度连接的重要桥梁。知广告推广不仅局限于传统意义上的硬性推广&#xff0c;更强…