Go Web下gin框架使用(一)

news2024/11/24 12:11:55

〇、前言

在前面,已经在这篇文章中详细地讨论了 gin 框架下的模板渲染问题,这篇文章主要对 gin 框架的使用进行讨论。

一、不同的路由

以下可以选择不同的路由进行渲染:

r := gin.Default()
	type usr struct {
		Name string `json:"name"`
		Msg  string
		Age  int
	}
	r.GET("/json", func(c *gin.Context) {
		data := gin.H{
			"name":    "小王子!",
			"massage": "hello",
			"age":     18,
		}
		c.JSON(http.StatusOK, data)
	})
	r.GET("/another_json", func(c *gin.Context) {
		data := usr{
			"小王子!",
			"hello,golang!",
			18,
		}
		c.JSON(http.StatusOK, data)
	})

当我们在浏览器中输入不同的 url (本例中仅仅是路径不同)时,服务器就会返回不同的数据,这是很好理解的。

(一)URL

URL是Uniform Resource Locator的缩写,它是用于标识互联网上资源位置的字符串。URL由几个组件组成,包括协议(如HTTP或HTTPS)、主机名、端口号(可选)、路径和查询参数(可选)。URL的主要目的是在网络上定位资源,如网页、图像、视频等。

下面是一个URL的示例:
https://www.example.com:8080/path/to/resource?param1=value1&param2=value2

在这个示例中:

  • 协议是HTTP(或HTTPS,如果使用加密连接;
  • 主机名是www.example.com;
  • 端口号是8080(在这个示例中是可选的,默认使用协议的默认端口);
  • 路径是/path/to/resource;
  • 查询参数是param1=value1和param2=value2(用于向服务器传递额外的信息);
  • URL在浏览器中用于访问网页,也在许多其他应用程序中用于定位网络资源。

二、查询参数的获取

当我们在浏览器中输入不同的参数事,服务器必须对这些参数进行获取和处理,这样才能正确处理用户的需求,返回用户想要的数据。比如我们在浏览器中输入:https://www.google.com/search?q=你好这个 q=你好就是参数字段。服务器获取到参数 q 后,就对你好进行查询,然后返回给用户,这样就完成了搜索。

一下是一个gin框架下的参数获取示例:


func main() {
	r := gin.Default()
	r.GET("/web", func(c *gin.Context) {
		// 获取浏览器发送的 query 字段
		// name := c.Query("query")
		// http://127.0.0.1:9001/web?query=杨超越&age=18
		name := c.DefaultQuery("query", "someone")
		age := c.DefaultQuery("age", "age")
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})
	r.Run(":9001")
}

main 函数的作用就是获取用户输入的 url 中的 query参数以及 age 参数,并处理。处理的过程具体为展示给用户他们输入的 nameage。运行结果为(杨超越 2023 年 5 月 31 日时的年龄为 24 岁,下面的年龄仅供参考):

在这里插入图片描述

三、获取表单数据

我们有时候会有让用户登录的需求,后台需要对用户输入的用户名以及登录密码进行判断和处理。实际上,一般返回这种数据就是表单数据的返回。在 gin 框架里有很方便的函数。以下是一个示例。

(一)表单数据的生成和处理

以下是一个网页 login.html,里面要求用户分别填写用户名以及密码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<form action="/login" method="post" novalidate autocomplete="off">
    <div>
        <label for="username">username:</label>
        <input type="text" name="username" id="username">
    </div>
    <div>
        <label for="password">password:</label>
        <input type="password" name="password" id="password">
    </div>
    <div>
        <input type="submit" value="登陆">
    </div>

</form>
</body>

</html>

这个html 文件有三个 type类型的数据,分别是type=“text”、type=“password”、type=“submit”,他是用 post 方法进行提交的。main函数是这样渲染的:

package main

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

func main() {
	r := gin.Default()
	r.LoadHTMLFiles("/Users/luliang/GoLand/gin_practice/chap8/login.html", "/Users/luliang/GoLand/gin_practice/chap8/index.html")
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.html", nil)
	})
	r.POST("/login", func(c *gin.Context) {
		// 获取 form 表单的数据
		//username := c.PostForm("username")
		//password := c.PostForm("password")
		// 第二种方式
		username := c.DefaultPostForm("username", "用户名")
		password := c.DefaultPostForm("password", "密码")
		c.HTML(http.StatusOK, "index.html", gin.H{
			"Name":     username,
			"Password": password,
		})
	})
	r.Run(":9001")

}

首先,通过GET方法渲染上述 login.html文件,然后 login文件中文submit 将会把表单返回到 context类型的 c:

	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.html", nil)
	})

之后,login 里面会用 POST 方法请求,在这个请求里,对该请求的处理方法是对另一个 html 文件进行渲染:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h1>hello,{{ .Name }}</h1>
<h1>你的密码是{{ .Password}}</h1>

</body>
</html>

这时,只需要把提价的数据从 c 中拿出来就好了:

// 获取 form 表单的数据
		//username := c.PostForm("username")
		//password := c.PostForm("password")
		// 第二种方式
		username := c.DefaultPostForm("username", "用户名")
		password := c.DefaultPostForm("password", "密码")

拿出来之后,就可以对我们的 html 文件进行渲染了:

	c.HTML(http.StatusOK, "index.html", gin.H{
			"Name":     username,
			"Password": password,
		})

运行结果为:

在这里插入图片描述
我们输入数据之后,点击登陆,进行POST 请求,渲染的新的结果为:

在这里插入图片描述

为了更清晰地展示这一过程,这里会用 Postman这个软件进行模拟。

(二)Postman进行分析

在这里插入图片描述

我们在对这个 url=http://127.0.0.1:9001/login进行 GET 请求时,可以看到服务器进行的是:

	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.html", nil)
	})

如果我们把 GET 请求换成 POST 请求,这时候就应该进行的是index.html渲染:

r.POST("/login", func(c *gin.Context) {
		// 获取 form 表单的数据
		//username := c.PostForm("username")
		//password := c.PostForm("password")
		// 第二种方式
		username := c.DefaultPostForm("username", "用户名")
		password := c.DefaultPostForm("password", "密码")
		c.HTML(http.StatusOK, "index.html", gin.H{
			"Name":     username,
			"Password": password,
		})
	})

在这里插入图片描述
打开检查器,也可以看到它进行的是 POST 请求,携带的参数为:在这里插入图片描述
渲染的是 index.html。
在这里插入图片描述

四、路径参数

路径参数和上面的参数不一样:

func main() {
	r := gin.Default()
	r.GET("/user/:name/:age", func(c *gin.Context) {
		name := c.Param("name")
		age := c.Param("age")
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})
	r.GET("/blog/:year/:month", func(c *gin.Context) {
		year := c.Param("year")
		month := c.Param("month")
		c.JSON(http.StatusOK, gin.H{
			"year":  year,
			"month": month,
		})
	})
	r.Run(":9001")

}

运行一下:

在这里插入图片描述
可以看到,服务端会将 URL 的路径参数提取出来并进行处理:

r.GET("/user/:name/:age", func(c *gin.Context) {
		name := c.Param("name")
		age := c.Param("age")
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})

五、参数绑定

为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。 下面的示例代码演示了.ShouldBind()强大的功能,它能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象:

func main() {
	type user struct {
		Username string `form:"username" json:"uname"`
		Password string `form:"password" json:"pwd"`
	}
	r := gin.Default()
	r.GET("/user", func(c *gin.Context) {
		var u user
		err := c.ShouldBind(&u) // 按值传递
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"msg":   "请求的参数不正确!",
				"error": err.Error(),
			})
		} else {
			c.JSON(http.StatusOK, gin.H{
				"message": "ok!",
				"user":    u,
			})
		}

	})
	r.POST("/user", func(c *gin.Context) {
		var u user
		err := c.ShouldBind(&u)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"msg":   "请求的参数不正确!",
				"error": err.Error(),
			})
		} else {
			c.JSON(http.StatusOK, gin.H{
				"message": "ok!",
				"user":    u,
			})
		}

	})

	r.Run(":9001")
}

看看这个请求的运行效果:
在这里插入图片描述
ShouldBind()就是这么强大!

六、文件上传

我们有时候需要对文件上传,上传文件在前端由用户进行操作,我们后端接收到用户文件上传的文件时,就对该文件进行一些可能的操作。
前端页面:

<!DOCTYPE html>
<html>
<head>
    <title>index</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="f1">
    <input type="submit" value="upload">
</form>
</body>
</html>

这里通过 post 方法,将文件submit 到了context 类型的 c对象中,我们继续处理:

r := gin.Default()
	r.LoadHTMLFiles("/Users/luliang/GoLand/gin_practice/chap11/index.html")
	r.GET("/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.html", nil)

	})
	r.POST("/upload", func(c *gin.Context) {
		// 读取文件
		f, err := c.FormFile("f1")
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
		} else {
			// 将读取的文件保存到本地
			// dsf := fmt.Sprintf("./%s", f.Filename)
			dsf := path.Join("./", f.Filename)
			err = c.SaveUploadedFile(f, dsf)
			if err != nil {
				return
			} // 将文件 f 保存到 dsf 中
			c.JSON(http.StatusOK, gin.H{
				"status": "OK",
			})

		}

	})

过程为,先通过 GET请求,访问到index.html:
在这里插入图片描述随便选一个文件:
在这里插入图片描述
点击上传:
在这里插入图片描述
在这个过程中,我们对 context 的c进行获取文件,存储并发送了一个合适的响应:

r.POST("/upload", func(c *gin.Context) {
		// 读取文件
		f, err := c.FormFile("f1")
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
		} else {
			// 将读取的文件保存到本地
			// dsf := fmt.Sprintf("./%s", f.Filename)
			dsf := path.Join("./", f.Filename)
			err = c.SaveUploadedFile(f, dsf)
			if err != nil {
				return
			} // 将文件 f 保存到 dsf 中
			c.JSON(http.StatusOK, gin.H{
				"status": "OK",
			})

		}
	})

七、路由重定向

这个过程很简单,就是当用户访问了某些请求之后,我们可以将该请求转接到另一个 URL 上去,类似于 DNS 劫持:

func main() {
	r := gin.Default()
	r.GET("/index", func(c *gin.Context) {
		//c.JSON(http.StatusOK,gin.H{
		//	"status":"Ok",
		//})
		c.Redirect(http.StatusMovedPermanently, "https://www.google.com")

	})
	r.GET("/a", func(c *gin.Context) {
		// 跳转到 b
		c.Request.URL.Path = "/b" // 修改请求 URL
		r.HandleContext(c)        // 继续处理 c

	})
	// 处理所有的方法
	r.GET("/b", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
		})

	})

	r.Run(":9001")

}

在这里插入图片描述
可以看到它重复定向到了url=http://127.0.0.1:9001/a

全文完,感谢阅读。

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

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

相关文章

八、go语言键盘输入和打印输出

键盘输入和打印输出 一、打印输出 1.1 fmt包 fmt包实现了类似C语言printf和scanf的格式化I/O。格式化verb&#xff08;‘verb’&#xff09;源自C语言但更简单。 详见官网fmt的API&#xff1a;https://golang.google.cn/pkg/fmt/ 1.2 导入包 import "fmt"1.3 常…

MyBatis——MyBatis项目搭建

但凡是框架&#xff0c;使用都是分三步走 1.导入jar文件&#xff0c;用maven导入 2.处理配置文件 3.开发业务代码 1.创建maven项目导入相关依赖 在pom文件中导入MyBatis相关依赖jar文件 安装lombok 在File->Settings Pugins 中安装lombok 要想启动lombok的话还需要在B…

GPT带你飞:Chat GPT吊打面试官,实时获取答案,分享调用OpenAI API key+完整源码脚本哦!

目录 福利&#xff1a;文末纯分享中文版CHAT GPT镜像&#xff0c;不存在魔法&#xff0c;纯分享免费使用 故事发生了 火爆GitHub 所以大家注意 网友看了之后调侃到&#xff0c;为了防止线上面试作弊&#xff0c;以后只好把面试都改成线下了。 如何安装 既然是调用GPT的AP…

nodejs基于vue的汽车订票客运站售票网站

使用Mysql创建数据表保存本系统产生的数据。系统可以提供信息显示和相应服务&#xff0c;其管理员负责审核会员充值&#xff0c;审核客户购票信息以及会员购票信息&#xff0c;管理客运班次与留言板&#xff0c;管理会员等级。客户查看客运班次&#xff0c;购买并支付车票&…

【Selenium】常用的Selenium基础使用模板和简单封装

前言 近来又用上了 Selneium &#xff0c;因为反复用到&#xff0c;所以在这里将一些常用的方法封装起来&#xff0c;方便后续的使用。 在这篇文章中&#xff0c;我们将探讨 Selenium 的基础模板和基础封装&#xff0c;以便更好地理解 Selenium 的使用方法。 在Selenium的使用…

python基础----03-----if语句、while、for循环、range语句、continue和break

一 布尔类型和比较运算符 1.1 布尔类型和比较运算符 定义变量存储布尔类型数据&#xff1a;变量名称 布尔类型字面量。 布尔类型不仅可以自行定义同时也可以通过计算的来。也就是使用比较运算符进行比较运算得到布尔类型的结果。在C/C中&#xff0c;比较运算符称之为关系运算…

如何解决航空企业数字化转型中的痛点?

数字化时代&#xff0c;越来越多的企业开始关注数字技术&#xff0c;希望通过数字化改造提高企业效率和竞争力&#xff0c;为企业创造更多的商机和利润。今天就来同大家探讨航空领域&#xff0c;小程序在企业数字化转型中发挥的作用、 航空业员工端App的敏捷转型挑战 技术上的…

Java 异常机制:是Java 提供的一种识别及响应错误的一致性机制。

。 目录 友情提醒第一章、异常概述1.1&#xff09;我们常说的异常是什么1.2&#xff09;异常的作用1.3&#xff09;Java异常体系和分类1.4&#xff09;演示异常的产生 第二章、定义异常与抛出异常&#xff1a;throw2.1&#xff09;自定义异常类&#xff1a;继承Exception或Run…

网络io与io多路复用select/poll/epoll

一、网络IO请求 网络I/O请求是指在计算机网络中&#xff0c;向其他主机或服务器发送请求或接收响应的操作。这些请求可以包括获取网页、下载文件、发送电子邮件等。网络I/O请求需要使用合适的协议和通信方式来进行数据传输&#xff0c;例如HTTP、FTP、SMTP等。 要完成一个完整…

字节面试过了,薪资都谈好了20K*13,结果挂在这里....

一般提到面试&#xff0c;肯定都会想问一下面试结果&#xff0c;我就大概的说一下面试结果&#xff0c;哈哈&#xff0c;其实不太想说&#xff0c;因为挺惨的&#xff0c;并没有像很多大佬一样 ”已拿字节阿里腾讯各大厂offer”&#xff0c;但是毕竟是自己的经历&#xff0c;无…

让效果图渲染做到最佳的几个小诀窍

制作出优秀的效果图需要多方面的技术支持&#xff0c;而渲染是其中非常关键的一步。一份精美的效果图需要经过高质量的渲染才能呈现出最佳的效果。本文将分享一些关于如何让效果图渲染做到最佳的小诀窍&#xff0c;包括专注的小细节、优化场景设置和灯光、纹理、图像应用最终修…

医疗电子红外线人体额温枪方案

在当前新冠疫情背景下&#xff0c;红外线人体额温枪成为疫情防控必备的设备之一。红外线人体额温枪采用红外线技术&#xff0c;无需接触人体&#xff0c;通过测量人体表面温度来判断人体是否发热。其测量快速、准确、不接触等特点&#xff0c;使其广泛应用于机场、车站、医院、…

数据结构之二叉树(Java)

在这里先说明一下&#xff0c;结点和节点其实一样的&#xff0c;无须关注这个。 一、树型结构 1. 概念&#xff1a;树是一种非线性的数据结构&#xff0c;它是由n个有限节点组成一个具有层次关系的集合。 如上图所示&#xff0c;把此种数据结构称作树是因为它看起来像一个倒挂…

校园高校教务选课成绩系统node.js+vue

系统主要实现了以下功能模块&#xff1a; 学籍信息 网上选课 网上评教&#xff0c;即对自己老师评分 任务查询&#xff0c;老师可以给学生发布任务&#xff08;类似于作业&#xff0c;考试&#xff09; 课表查询&#xff0c;希望有个图形化的课表&#xff0c;而不是表格式 教室…

Mysql InnoDB的Buffer Pool

Buffer Pool 在MySQL服务器启动的时候就向操作系统申请了⼀⽚连续的内存&#xff0c;他们给这⽚内存起了个名&#xff0c;叫做Buffer Pool&#xff08;中⽂名 是缓冲池&#xff09;。 默认情况下Buffer Pool只有128M⼤⼩&#xff0c;最⼩值为5M&#xff0c;通过修改配置文件设…

【Linux开发—多进程编程】

【Linux开发—多进程编程】 前言1&#xff0c;两种类型的服务端2&#xff0c;并发服务器的实现方法&#xff1a; 一&#xff0c;认识及应用1&#xff0c;进程认识2&#xff0c;CPU核的个数与进程数3&#xff0c;进程ID4&#xff0c;进程创建5, 调用fork函数后的程序运行流程: 二…

一文了解PWA——Progressive Web App

近年来&#xff0c;出现了一种新的应用开发模式——PWA&#xff08;Progressive Web App&#xff0c;即渐进式Web应用&#xff09;。今天就来为大家分享什么是PWA&#xff0c;以及它与小程序的区别、技术原理。 PWA的基本概念和技术原理 PWA是一种基于Web技术的应用开发模式&a…

基于CC2530设计智慧农业控制系统

一、项目背景 智慧农业是近年来发展迅速的领域,其目的是利用先进的传感技术、物联网技术和云计算技术等,实现自动化、智能化的农业生产管理,并提高农业生产效率和质量。本文基于CC2530设计了一种智慧农业控制系统,采用DHT11模块、BH1750模块和土壤湿度传感器等传感器,通过…

turtle和matplotlib画画:圆形、爱心

马上就要到六一儿童节了&#xff0c;小朋友很喜欢画画&#xff0c;这里就用Pyhton来画一些简单形状&#xff1a; 用turtle画圆形 import turtle# 设置画笔颜色和粗细 turtle.pencolor("black") turtle.pensize(5)# 绘制一个半径为100的圆形 turtle.circle(100)# 隐藏…

jsonp的实现原理

什么是跨域&#xff1a; 跨域是浏览器同源策略而产生的&#xff0c;在不同协议&#xff0c;不同端口&#xff0c;不同域名下&#xff08;以上任意一个不同都算是跨域&#xff09;的客服端和服务端之间是无法互相访问的。 举例&#xff1a; http://www.baidu.com/index.html …