gin数据解析,绑定和渲染
一. 数据解析和绑定
1.1 Json数据解析和绑定
html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="/loginForm" method="post"enctype="application/x-www-form-urlencoded">
用户名<input type="text" name="username"><br>
密码<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
代码:
- gin.Context中的ShouldBind方法将请求中的正文中的数据,自动按照json格式解析到结构体。
package mainimport ("net/http""github.com/gin-gonic/gin"
)// 定义接收数据的结构体
type Login struct {//binding:"required"修饰字段,若接收为空值,则报错Account string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`Passwd string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}func main() {//创建路由r := gin.Default()//设置HTML文件所在目录r.LoadHTMLGlob("./*.html")r.GET("/", func(c *gin.Context) {//发送html文件内容c.HTML(http.StatusOK, "index.html", nil)})r.POST("/loginForm", func(c *gin.Context) {//声明接收变量var json Login//将request的body中的数据,自动按照json格式解析到结构体if err := c.ShouldBindJson(&json); err != nil {//gin.H封装了生成json数据工具c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}//判断用户名密码是否正确if json.Account != "root" || json.Passwd != "admin" {c.JSON(http.StatusBadRequest, gin.H{"status": ".304",})return}c.JSON(http.StatusOK, gin.H{"status": "ok",})})r.Run()
}
演示:

1.2. 表单数据解析和绑定
html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="/loginForm" method="post"enctype="application/x-www-form-urlencoded">
用户名<input type="text" name="username"><br>
密码<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
代码:
- gin.Context的Bind方法默认解析并绑定form格式,根据请求头中的content-type自动推断。
package mainimport ("net/http""github.com/gin-gonic/gin"
)// 定义接收数据的结构体
type Login struct {//binding:"required"修饰字段,若接收为空值,则报错Account string `form:"username" binding:"required"`Passwd string `form:"password" binding:"required"`
}func main() {//创建路由r := gin.Default()//设置HTML文件所在目录r.LoadHTMLGlob("./*.html")r.GET("/", func(c *gin.Context) {//发送html文件内容c.HTML(http.StatusOK, "index.html", nil)})r.POST("/loginForm", func(c *gin.Context) {//声明接收变量var form Login//Bind()默认解析并绑定form格式//根据请求头中的content-type自动推断if err := c.Bind(&form); err != nil {//gin.H封装了生成json数据工具c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}//判断用户名密码是否正确if form.Account != "root" || form.Passwd != "admin" {c.JSON(http.StatusBadRequest, gin.H{"status": ".304",})return}c.JSON(http.StatusOK, gin.H{"status": "ok",})})r.Run()
}
1.3. URI数据解析和绑定
- gin.Context中的ShouldBindUri方法将uri中的数据,自动按照uri格式解析到结构体。
package mainimport ("net/http""github.com/gin-gonic/gin"
)// 定义接收数据的结构体
type Login struct {//binding:"required"修饰字段,若接收为空值,则报错Account string `uri:"user" binding:"required"`Passwd string `uri:"password" binding:"required"`
}func main() {//创建路由r := gin.Default()r.GET("/:user/:password", func(c *gin.Context) {//声明接收变量var uri Loginif err := c.ShouldBindUri(&uri); err != nil {//gin.H封装了生成json数据工具c.JSON(http.StatusBadRequest, gin.H{"error": err.Error(),})return}//判断用户名密码是否正确if uri.Account != "root" || uri.Passwd != "admin" {c.JSON(http.StatusBadRequest, gin.H{"status": ".304",})return}c.JSON(http.StatusOK, gin.H{"status": "ok",})})r.Run()
}
演示:


二. gin渲染
2.1 各种数据的响应
多种响应方式:
package mainimport ("net/http""github.com/gin-gonic/gin""github.com/gin-gonic/gin/testdata/protoexample"
)func main() {r := gin.Default()//1. jsonr.GET("/someJson", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "someJson","status": "ok",})})//2. 结构体响应r.GET("/someStruct", func(c *gin.Context) {var msg struct {Name stringMessage stringNumber int}msg.Name = "root"msg.Message = "someStruct"msg.Number = 1c.JSON(http.StatusOK, msg)})//3. xmlr.GET("/someXml", func(c *gin.Context) {c.XML(http.StatusOK, gin.H{"message": "abc"})})//4. YAML响应r.GET("/someYaml", func(c *gin.Context) {c.YAML(http.StatusOK, gin.H{"message": "123",})})//5. protobuf格式//构建一个自己的传输格式r.GET("/someProtobuf", func(c *gin.Context) {resp := []int64{int64(1), int64(2)}lable := "lable"data := &protoexample.Test{Label: &lable,Reps: resp,}c.ProtoBuf(http.StatusOK, data)})r.Run()
}
2.2 HTML模板渲染
- gin支持加载HTML模板,然后根据模板进行配置并返回相应的数据,本质就是字符串替换。
- LoadHTMLGlob()方法可以加载模板文件
目录结构:

html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{.title}}</title>
</head>
<body>
fgkjdskjdsh{{.ce}}
</body>
</html>
代码:
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.LoadHTMLGlob("./tem/*") //从运行文件位置开始 需要加载的html文件路径r.GET("/someHtml", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)})r.Run()
}
- 当html的目录结构如下时

html:
{{ define "user/index.html" }}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>{{.title}}</title>
</head><body>fgkjdskjdsh{{.message}}</body>
</html>
{{ end }}
代码:
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.LoadHTMLGlob("tem/*/*") //从运行文件位置开始 需要加载的html文件路径r.GET("/someHtml", func(c *gin.Context) {//user/index.html为html中的definec.HTML(http.StatusOK, "user/index.html", gin.H{"title": "我是测试", "message": "123"})})r.Run()
}
演示:

- html头尾分离

代码:
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.LoadHTMLGlob("tem/*/*") //从运行文件位置开始 需要加载的html文件路径r.GET("/someHtml", func(c *gin.Context) {//user/index.html为html中的definec.HTML(http.StatusOK, "user/index.html", gin.H{"title": "我是测试", "message": "123"})})r.Run()
}
演示:

- 如果你需要引入静态文件需要定义一个静态文件目录
r.Static("./assets", "./assets")
2.3 重定向
- 使用gin.Context的Redirect方法
package mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/index", func(c *gin.Context) {//重定向c.Redirect(http.StatusMovedPermanently, "redirect")})r.GET("/redirect", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "hello",})})r.Run()
}

2.4 同步异步
- goroutine机制可以方便地实现异步处理
- 另外,在启动新的goroutine时,不应该使用原始上下文context,必须使用它的只读副本
package mainimport ("log""time""github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/long_async", func(c *gin.Context) {//上下文副本c_tmp := c.Copy()//异步处理go func() {time.Sleep(2 * time.Second)log.Println("异步执行 " + c_tmp.Request.URL.Path)}()})r.GET("/long_sync", func(c *gin.Context) {time.Sleep(3 * time.Second)log.Println("同步执行 " + c.Request.URL.Path)})r.Run()
}
异步是启动一个协程去执行请求。

相关文章:
gin数据解析,绑定和渲染
一. 数据解析和绑定 1.1 Json数据解析和绑定 html文件: <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0&quo…...
Django 对模型创建的两表插入数据
1,添加模型 Test/app8/models.py from django.db import modelsclass User(models.Model):username models.CharField(max_length50, uniqueTrue)email models.EmailField(uniqueTrue)password models.CharField(max_length128) # 使用哈希存储密码first_name …...
Lua: 轻量级多用途脚本语言
Lua 是一种高效而轻量级的脚本语言,具备强大的扩展性和灵活性,广泛应用于游戏开发、嵌入式系统、Web 应用等多个领域。本文将深入探讨 Lua 的特性、应用场景以及如何使用 Lua 进行开发。 1. Lua 的起源与发展 Lua 的发展始于上世纪90年代初,…...
PotPlayer安装及高分辨率设置
第1步: 下载安装PotPlayer软件 PotPlayer链接:https://pan.baidu.com/s/1hW168dJrLBonUnpLI6F3qQ 提取码:z8xd 第2步: 下载插件,选择系统对应的位数进行运行,该文件不能删除,删除后将失效。 …...
实现写入缓存策略的最佳方法探讨
实现写入缓存策略的最佳方法探讨 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨在软件开发中实现写入缓存策略的最佳方法。缓存在提升应用性能和…...
【Day03】0基础微信小程序入门-学习笔记
文章目录 视图与逻辑学习目标页面导航1. 声明式导航2. 编程式导航3. 导航传参 页面事件1. 下拉刷新2. 上拉触底3.扩展-自定义编译模式 生命周期1. 简介2. 生命周期函数3. 应用的生命周期函数4. 页面生命周期函数 WXS脚本1. 概述2. 基础语法3. WXS的特点4. 使用WXS处理手机号 总…...
libctk shared library的设计及编码实践记录
一、引言 1.1 <libctk>的由来 1.2 <libctk>的设计理论依据 1.3 <libctk>的设计理念 二、<libctk>的依赖库 三、<libctk>的目录说明 四、<libctk>的功能模块及使用实例说明 4.1 日志模块 4.2 mysql client模块 4.3 ftp client模块 4…...
【代码随想录训练营】【Day 65】【图论-2】| 卡码 99
【代码随想录训练营】【Day 65】【图论-2】| 卡码 99 需强化知识点 深度搜索和广度搜索 题目 99. 岛屿数量 思想:遍历到为1的节点,再搜索标记,每遇到新的陆地节点,增加计数 深度搜索广度搜索:此处用 [] 作为待遍…...
【动态规划】139. 单词拆分
139. 单词拆分 难度:中等 力扣地址:https://leetcode.cn/problems/word-break/description/ 问题描述 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意:不要求字…...
【C++】空指针访问成员函数
空指针访问成员函数 C中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针 如果用到this指针,需要加以判断保证代码的健壮性 class Animal { public:void fun1() {//正常的成员函数}void fun2() {if (this NULL) {return;//如果没有这个…...
Linux的IO易错点总结
本文主要记录IO的一些易错操作。 阻塞IO和非阻塞IO,一般都是针对数据读取的,因为write是主动行为,不存在阻塞这一说。 非阻塞式IO,一般都要配合while轮询来读取数据。 IO多路复用 当只检测一路IO的时候,和普通IO的作…...
【Android面试八股文】说一说你对Android中的Context的理解吧
文章目录 一、Context是什么?1.1 主要功能和用途1.2 如何获取 Context 实例?1.3 注意事项二、Context 类的层次结构三、Context的数量四、Context的注意事项五、Android 中有多少类型的 Context,它们有什么区别 ?六、Contextlmpl实例是什么时候生成的,在 Activity 的 oncr…...
AI在音乐创作中的角色:创造还是毁灭?
目录 一、基本情况介绍 二、近期新闻 三、AI生成音乐方面的商业模式 四、人工智能和音乐人可能的合作模式 五、人们如何借助AI来创作音乐 六、人工智能在创意产业引发的伦理道德问题 七、如何平衡技术发展与提高人类创造积极性的关系? 总结 一、基本情况介绍…...
[深入理解DDR] 总目录
依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解DDR》 蓝色的是传送门,点击链接即可到达指定文章。 图。 DDR 分类 导论 [RAM] DRAM 导论:DDR4 | DDR5 | LPDDR5 | GDRR6 | HBM 应运而生 运存与内存?内存与存…...
模板方法模式在金融业务中的应用及其框架实现
引言 模板方法模式(Template Method Pattern)是一种行为设计模式,它在一个方法中定义一个算法的框架,而将一些步骤的实现延迟到子类中。模板方法允许子类在不改变算法结构的情况下重新定义算法的某些步骤。在金融业务中ÿ…...
leetcode347.前k个高频元素
leetcode347.前k个高频元素 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 示例 1: 输入: nums [1,1,1,2,2,3], k 2 输出: [1,2] 示例 2: 输入: nums [1], k 1 输出: [1] 优先队列法 struct hash_…...
c++(二)
1. 类和对象 1.1. 封装 封装的意义 将属性和行为作为一个整体,表现生活中的事物;将属性和行为加以权限控制 public -> 公共权限:类内可以访问,类外也可以访问protected -> 保护权限:类内可以访问,…...
基于PHP的初中数学题库管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的初中数学题库管理系统 一 介绍 此初中数学题库管理系统基于原生PHP开发,数据库mysql,系统角色分为学生,教师和管理员。(附带参考设计文档) 技术栈:phpmysqlphpstudyvscode 二 功能 …...
WDG看门狗
1 WDG 1.1 简介 WDG是看门狗定时器(Watchdog Timer)的缩写,它是一种用于计算机和嵌入式系统中的定时器,用来检测和恢复系统故障。 看门狗就像是一个忠诚的宠物狗,它时刻盯着你的程序,确保它们正常运行。…...
zabbix server client 安装配置
Zabbix Server 采用源码包部署,数据库采用 MySQL8.0 版本,zabbix-web 使用 nginxphp 来实现。具体信息如下: 软件名 版本 安装方式 Zabbix Server 6.0.3 源码安装 Zabbix Agent 6.0.3 源码安装 MySQL 8.0.28 yum安装 Nginx 1.20…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
