go-gin

前置

gin是go的一个web框架,我们简单介绍一下gin的使用

导入gin :"github.com/gin-gonic/gin" 我们使用import导入gin的包

简单示例:

package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello world",})})r.Run(":8080")
}

这里定义了一个简单gin-web。我们可以在浏览器中通过访问:localhost:8080/这个url,它会显示

{"message": "hello world"
}

创建路由引擎以及设置路由

创建引擎

创建路由引擎的方式有两种

r := gin.Default()  //默认的,内置logger recovery这两个中间件
r := gin.New()      //空的,没有内置中间件

中间件:假设后端是a,前端是b。中间件就是在a和b之间的一个东西,我们根据中间件可以做很多东西。关于中间件的部分我们后面会讲到

 设置路由

设置路由也有两种方法,第一种是一个一个的设置路由

func main() {r := gin.Default()r.GET("/u/a", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello a",})})r.GET("/u/b", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello b",})})r.GET("/u/c", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello c",})})r.GET("/u/d", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello d",})})r.Run(":8080")
}

这样一个一个的设置虽然简单,但是看起来会很臃肿。而且我们发现它们前面都是 /u的路由,这样设置还容易看错。那我们来看第二种方法:路由分组

路由分组

我们通过 Group方法来设置分组,它的参数就是这个组的前置路由,它会返回一个routergroup的指针,我们通过这个指针来设置后续的子路由

func main() {r := gin.Default()group := r.Group("/u")//设置路由组{group.GET("/a", func(c *gin.Context) {//添加组员ac.JSON(200, gin.H{"message": "hello world",})})group.GET("/b", func(c *gin.Context) {//添加组员bc.JSON(200, gin.H{"message": "hello world",})})group.GET("/c", func(c *gin.Context) {//添加组员cc.JSON(200, gin.H{"message": "hello world",})})group.GET("/d", func(c *gin.Context) {//添加组员dc.JSON(200, gin.H{"message": "hello world",})})}r.Run(":8080")//启动
}

这样分组方便我们后续阅读代码以及中间件设置。

数据获取

获取url中的变量

路径参数

group.POST("/c/:name", func(c *gin.Context) {//这里的请求也可以是get或其他请求name := c.Param("name")c.JSON(200, gin.H{"message": name,})})

我们使用c.Param("name")获取到变量,然后返回数据。

一个路由可以携带多个变量,如 /c/:name/:age 这样我们访问的时候就可以携带两个变量了

查询参数

查询参数的设置如下

group := r.Group("/u"){group.POST("/c", func(c *gin.Context) {//路由设置没有改变name := c.Query("name")//使用Query查询c.JSON(200, gin.H{"message": name,})})}

这种方式传参的时候需要用 /u/c?name=xxx 这种方式传参,路由后面加个 ?key=value多个参数用&连接

获取表单数据

前端有时候会返回一个表单的数据,我们需要从表单中获取我们需要的数据。这里我们一般都使用post请求,因为它不会把信息显示在url中。get请求也可以但是我们只有在特定的情况下才会使用get请求(因为url的长度有限制)

这里的请求方法取决于表单的method
form表单有两个属性,一个method指定请求方法,一个action指定请求的url。

post请求获取表单数据

<form action="http://localhost:8080/u/c" method="POST"><input type="text" name="name"><input type="text" name="pass"><input type="submit" value="submittt">
</form>

这是一个简单的表单,里面包含name、id还有一个提交按钮。请求方法为post,提交到http://localhost:8080/u/c这个url

我们如果要获取它的表单数据,需要知道提交过来的数据的 name 属性是什么,然后使用PostForm获取

func main() {r := gin.Default()group := r.Group("/u"){group.POST("/c", func(c *gin.Context) {name := c.PostForm("name")//对应表单name属性为name的文本域pass := c.PostForm("pass")//对应表单name属性为pass的文本域fmt.Println(name, pass)c.JSON(http.StatusOK, gin.H{"name": name,"pass": pass,})})}r.Run(":8080")
}

如果要获取单选框也是使用PostForm。多选框则是PostFormArray,而且返回的是一个string类型的切片
多选框内,多个相同的name属性的选择是一组,value属性对应获取到的值是什么

html代码

<form action="http://localhost:8080/u/c" method="POST" ><input type="checkbox" name="remember" value="1"><input type="checkbox" name="remember" value="2"><input type="checkbox" name="remember" value="3"><input type="checkbox" name="remember" value="4"><input type="submit" value="submittt">
</form>

go代码

func main() {r := gin.Default()group := r.Group("/u"){group.POST("/c", func(c *gin.Context) {arr := c.PostFormArray("remember")fmt.Println(reflect.TypeOf(arr))c.JSON(http.StatusOK, gin.H{"arr": arr,})})}r.Run(":8080")
}

post请求获取表单文件

有的时候表单也是需要上传一些文件的,这时候就需要我们获取文件信息了

首先是表单部分,在表单的头部我们需要添加  enctype="multipart/form-data"这个属性来说明是含文件的上传

<form action="http://localhost:8080/u/c" method="POST" enctype="multipart/form-data" ><input type="file" name="file"><input type="submit" value="submittt">
</form>

后端获取的时候需要使用c.FormFile()

group.POST("/c", func(c *gin.Context) {file, err := c.FormFile("file")//返回文件和错误信息if err != nil {fmt.Println("err:", err)return} else {fmt.Println(file.Filename)//文件名fmt.Println(file.Size)//文件大小os.MkdirAll("./tmp", os.ModePerm)//新建一个目录,如果目录存在就不会报错,而是直接跳过err := c.SaveUploadedFile(file, "./tmp/"+file.Filename)//保存if err!= nil {错误处理}}})

我们如果需要保存文件就要使用 c.SaveUploadedFile(file, "保存路径"+file.Filename),这个路径需要我们提前创建好。它会返回一个错误信息,我们可以根据错误信息来判断是否存储成功

gin的中间件

中间件的本质就是一个函数,该函数的作用是检查某些数据是否是正常数据,从而决定是否继续执行

设置中间件的方法主要有以下几种

  1. 全局设置         --   设置到路由引擎上
  2. 单个路由设置  --   设置到单个的路由上
  3. 路由组设置      --    设置到一个路由组上
func main() {r := gin.New()r.Use()//全局引用中间件group := r.Group("/u").Use()//路由组引用中间件{group.GET("/a", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello world",})})}r.GET("/b", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello world",})}).Use()//单个路由引用中间件r.Run(":8080")
}

中间件执行的顺序是和引用的顺序有关

.Use(中间件a,b,c,d)这里引用了四个中间件,当我访问对应的路由的时候这四个中间件会按照abcd的顺序挨个执行

var str stringfunc A() gin.HandlerFunc {return func(c *gin.Context) {str = str + "a "}
}
func B() gin.HandlerFunc {return func(c *gin.Context) {str = str + "b "}
}
func C() gin.HandlerFunc {return func(c *gin.Context) {str = str + "c "}
}
func D() gin.HandlerFunc {return func(c *gin.Context) {str = str + "d "}
}func main() {r := gin.New()r.Use(A(), B(), C(), D()) //全局引用中间件r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"str:": str,})})r.Run(":8080")
}

我们访问http://localhost:8080/这个路由的时候网页上显示的就是{"str:":"a b c d "}

这就是基础的中间件使用,假设abcd是四个不同的验证件,其中一个出错就不能继续执行后面的了,而是返回错误信息。这里我们要使用的是c.Abrot() c.Next()两个流程控制函数

c.Next()这个函数的作用就是允许执行后续中间件以及最终处理函数
c.Abrot()这个函数就是不执行后续的中间件和最终处理函数
无论是abrot还是next,它们所在的中间件都会完整的执行,除非return了。

var str stringfunc A() gin.HandlerFunc {return func(c *gin.Context) {if str == "" {//判断是否正确,正确则拼接字符串,否则报错str = str + "a "c.Next()} else {c.AbortWithStatus(http.StatusNotAcceptable)		}}
}
func B() gin.HandlerFunc {return func(c *gin.Context) {if str == "a " {str = str + "b "c.Next()} else {c.AbortWithStatus(http.StatusNotAcceptable)		}}
}
func C() gin.HandlerFunc {return func(c *gin.Context) {if str == "a b " {str = str + "c "c.Next()} else {c.AbortWithStatus(http.StatusNotAcceptable)}}
}
func D() gin.HandlerFunc {return func(c *gin.Context) {if str == "a b c " {str = str + "d "c.Next()} else {c.AbortWithStatus(http.StatusNotAcceptable)		}}
}
func main() {r := gin.New()r.Use(A(), B(), C(), D()) //全局引用中间件r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"str:": str,})})r.Run(":8080")
}

这里的abort有多个版本

  1. Abort()
  2. AbortWithStatus(状态码)
  3. AbortWithStatusJSON(状态码,gin.H{key:value})

前两个访问的时候浏览器都是访问错误,后面的会返回我们的json数据到浏览器上

gin加载HTML

gin设置静态资源目录

r.Static("/static", "./static")
当我们访问/static的时候就是访问的项目中的./static,也就是说可以在浏览器访问一些文件。

加载HTML模板

r.LoadHTMLGlob("templates/*")         加载templates下的所有.html文件
 

返回HTML文件

使用c.HTML(状态码,“html文件”,gin.H{})

这里要注意的是我们如果使用r.LoadHTMLGlob("templates/*") 之后,单独的一个index.html文件其实就是加载的templates/index.html文件

最后的gin.H{}是传入模板的数据,它传递的是key:value的形式,前端html文件可以通过{{.key}}来访问这个value

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

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

相关文章

C# NX二次开发:判断两个体是否干涉和获取系统日志的UFUN函数

大家好&#xff0c;今天要讲关于如何判断两个体是否干涉和获取系统日志的UFUN函数。 &#xff08;1&#xff09;UF_MODL_check_interference&#xff1a;这个函数的定义为根据单个目标体检查每个指定的工具体是否有干扰。 Defined in: uf_modl.h Overview Checks each sp…

如何解决 Linux 系统文件描述符耗尽的问题

在Linux系统中&#xff0c;文件描述符&#xff08;File Descriptor, FD&#xff09;是操作系统管理打开文件、套接字、管道等资源的抽象标识。当进程或系统耗尽文件描述符时&#xff0c;会导致服务崩溃、连接失败等严重问题。以下是详细的排查和解决方案&#xff1a; --- ###…

LVGL简易计算器实战

文章目录 &#x1f4c1; 文件结构建议&#x1f539; eval.h 表达式求值头文件&#x1f539; eval.c 表达式求值实现文件&#xff08;带详细注释&#xff09;&#x1f539; ui.h 界面头文件&#x1f539; ui.c 界面实现文件&#x1f539; main.c 主函数入口✅ 总结 项目效果&…

使用countDownLatch导致的线程安全问题,线程不安全的List-ArrayList,线程安全的List-CopyOnWriteArrayList

示例代码 package com.example.demo.service;import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class UnSafeCDTest {Executor…

ALLinSSL:一站式SSL证书管理解决方案

引言 在当今互联网安全日益重要的背景下,SSL证书已成为保护网站安全的必备工具。然而,管理多个SSL证书常常是一项繁琐且容易出错的任务。ALLinSSL应运而生,它提供了一个一站式的SSL证书管理解决方案,大大简化了证书的申请、安装和更新过程。本文将深入介绍ALLinSSL的特性、…

嵌入式通信协议总览篇:万物互联的基石

嵌入式系统的世界,是靠协议“说话”的世界。 在你设计一个智能设备、构建一个工业控制系统、开发一款 IoT 网关时,一个核心问题始终绕不开:**这些设备之间如何“对话”?**答案就是——通信协议。 本篇作为系列第一章,将带你全面理解嵌入式通信协议的全貌,为后续深入学习…

【数据结构】红黑树(C++)

目录 一、红黑树的概念 二、红黑树的性质 三、红黑树结点定义 四、红黑树的操作 1. 插入操作 1.1 插入过程 1.2 调整过程 1.2.1 叔叔节点存在且为红色 1.2.2 叔叔节点存在且为黑色 1.2.3 叔叔节点不存在 2. 查找操作 2.1 查找逻辑 2.2 算法流程图 2.3 使用示例 …

Oracle数据库DBF文件收缩

这两天新部署了一套系统&#xff0c;数据库结构保持不变&#xff0c;牵扯导出表结构还有函数&#xff0c;图省事就直接新建用户&#xff0c;还原数据库了。然后咔咔咔&#xff0c;一顿删除delete&#xff0c;truncate&#xff0c;发现要不就是表删了&#xff0c;还有num_rows&a…

【字节拥抱开源】字节豆包团队开源首发 Seed-Coder 大模型

我们非常高兴地向大家介绍 Seed-Coder&#xff0c;它是一个功能强大、透明、参数高效的 8B 级开源代码模型系列&#xff0c;包括基础变体、指导变体和推理变体。Seed-Coder 通过以下亮点促进开放代码模型的发展。 以模型为中心&#xff1a;Seed-Coder主要利用大语言模型&#…

Qt 无边框窗口,支持贴边分屏

常规操作, 无法进行窗口的大小缩放和移动贴边分屏等操作 // 去掉标题栏,去掉工具栏&#xff0c;窗口置顶 setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);重点介绍 QWindowKit https://github.com/stdware/qwindowkit 跨平台的支持Windows\…

Qt 样式表:全面解析与应用指南

在 Qt 开发中,样式表(Style Sheets)是定义应用程序界面外观的关键工具。它采用文本格式的规则集合,借鉴了 CSS 语法,借助选择器、属性和值,能精准把控各类控件的外观表现,极大提升了界面设计的灵活性与美观性。 文章目录 一、样式可更改的效果​1、颜色相关效果​2、字体…

追踪大型语言模型的思想(上)(来自针对Claude的分析)

概述 像 Claude 这样的语言模型并非由人类直接编程&#xff0c;而是通过大量数据进行训练。在训练过程中&#xff0c;它们会学习解决问题的策略。这些策略被编码在模型为每个单词执行的数十亿次计算中。对于我们这些模型开发者来说&#xff0c;这些策略是难以捉摸的。这意…

Python pandas 向excel追加数据,不覆盖之前的数据

最近突然看了一下pandas向excel追加数据的方法&#xff0c;发现有很多人出了一些馊主意&#xff1b; 比如用concat,append等方法&#xff0c;这种方法的会先将旧数据df_1读取到内存&#xff0c;再把新数据df_2与旧的合并&#xff0c;形成df_new,再覆盖写入&#xff0c;消耗和速…

MYSQL 索引和事 务

目录 一 MYSQL 索引介绍 1.索引概念 2.索引作用 3.索引的分类 3.1普通索引 3.2唯一索引 3.3组合索引&#xff08;最左前缀&#xff09; 3.4全文索引 4.3查看索引 4.4删除索引 二 MYSQL事务 一&#xff1a;MYSQL索引介绍 索引是一个排序的列表,在这个列表中存储着索…

【C/C++】ARM处理器对齐_伪共享问题

文章目录 1 什么是伪共享&#xff1f;2 为什么对齐&#xff1f;3 伪共享的实际影响4 为什么必须是 64 字节&#xff1f;5 其他替代方案6 验证对齐效果总结 1 什么是伪共享&#xff1f; 伪共享是 多线程编程中的一种性能问题&#xff0c;其本质是&#xff1a; 缓存行&#xff…

Kafka Controller的作用是什么?故障时如何恢复? (管理分区和副本状态;通过ZooKeeper选举新Controller)

Apache Kafka Controller 是 Kafka 集群的核心协调组件&#xff0c;主要承担两大核心职责&#xff1a; 一、核心作用 分区领导者选举 1 // 分区领导者选举逻辑示例&#xff08;伪代码&#xff09; def electLeader(partition: Partition): Unit {val isr partition.inSync…

阿里云前端Nginx部署完,用ip地址访问却总访问不到,为什么?检查安全组是否设置u为Http(80)!

根据你的描述&#xff0c;Ping测试显示数据包无丢失但无法通过公网IP访问服务&#xff0c;说明网络基础层&#xff08;ICMP协议&#xff09;是通畅的&#xff0c;但更高层&#xff08;如TCP/UDP协议或服务配置&#xff09;存在问题。以下是系统性排查与解决方案&#xff1a; 一…

关于STM32 SPI收发数据异常

问题描述&#xff1a; STM32主板做SPI从机&#xff0c;另一块linux主板做主机&#xff0c;通信的时候发现从机可以正确接收到主机数据&#xff0c;但是主机接收从机数据时一直不对&#xff0c;是随机值。 问题原因&#xff1a; 刚发现问题的时候&#xff0c;用逻辑分析仪抓包…

特励达力科LeCroy推出Xena Freya Z800 800GE高性能的800G以太网测试平台

Xena Freya Z800 800GE 是由全球领先的测试与测量解决方案提供商特励达力科公司&#xff08;Teledyne LeCroy&#xff09;开发的高性能以太网测试平台&#xff0c;专为满足从10GE到800GE数据中心互连速度的需求而设计。特励达力科公司在网络测试领域拥有超过50年的技术积累&…