Gin框架入门

news2024/10/7 10:17:39

介绍

  • Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点

  • 对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的net/http足够简单,性能也非常不错

  • 借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范

安装

要安装Gin软件包,您需要安装Go并首先设置Go工作区。

1.首先需要安装Go(需要1.10+版本),然后可以使用下面的Go命令安装Gin。
如果大家是使用GoLand编辑器的话,可以直接在命令行窗口里面运行下面的命令

go get -u github.com/gin-gonic/gin

2.将其导入您的代码中:

import “github.com/gin-gonic/gin”

3.(可选)导入net/http。例如,如果使用常量,则需要这样做http.StatusOK。

import “net/http”

简单案例

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	// 1.创建路由
	r := gin.Default()//创建的Engine
	// 2.绑定路由规则,执行的函数
	// gin.Context,封装了request和response
	r.GET("/:name", func(c *gin.Context) {
		name := c.Param("name")//参数路由
		id := c.Query("id")//查询参数
		c.String(http.StatusOK, "hello World! ,%s ,id is %s", name, id)
	})
	// 3.监听端口,默认在8080
	// Run("里面不指定端口号默认为8080")
	err := r.Run(":8000")
	if err != nil {
		return
	}
}

执行结果如下:
在这里插入图片描述

这样一个简单Gin使用案例就实现了。接着我们执行该文件,命令行窗口中看到输出监听端口就说明已经启动成功了
在这里插入图片描述
启动失败的最常见原因就是端口失败了,下面是一个端口占用的错误。
在这里插入图片描述

gin.Engine

在Gin里面,一个web服务器被抽象成为Engine。你可以在一个应用里面创建多个Engine实例,监听不同的端口。
Engine承担了路由注册、接入middleware的核心职责。,笔者在查看源码的时候,发现Engine其实是组合了RouterGroup,RouterGroup才是实现路由功能的核心组件。
在这里插入图片描述

gin.Context

gin.Context是Gin里面的核心类型,该类十分重要,我们会频繁与其打交道。
在Gin里面,它的核心职责有两个:

  • 处理请求
  • 返回响应

在这里插入图片描述
上图中的Request代表的就是请求,Writer代表的就是响应。

Gin路由注册

Gin为每一个HTTP方法(最常用的就是Get和Post)都提供了一个注册路由的方法。

基本上都是两个参数:

  • 路由规则:比如说/hello这种静态路由。
  • 处理函数;也就是我们注册的,返回hello,world的方法。

路由分类

  • 静态路由:完全匹配的路由,也就是前面我们注册的hello的路由。
  • 参数路由:在路径中带上了参数的路由。
  • 通配符路由:任意匹配的路由。
	r.GET("/views?id=*.html", func(context *gin.Context) {
		path := context.Param(".html")
		context.String(http.StatusOK, "匹配上的值是,%s", path)
	})

在这里插入图片描述
在这里插入图片描述

该用什么方法?什么路由?

在面对一个业务的时候,该怎么设计路由?

  • 应该用GET方法还是POST方法?
  • 该用路由参数?还是查询参数?还是把参数放到body里面?

适用于初学者的两条原则:

  • 用户是查询数据的,用GET,参数放到查询参数里面,即?a=123这种。
  • 用户是提交数据的,用POST,参数全部放到Body里面。

使用Gin设计一个用户模块相关的接口

对于一个用户模块来说,最先要设计的接口就是:注册和登录。
而后要考虑提供:编辑和查看用户信息。

这里,我们直接定义一个UserHandler,然后将所有和用户有关的路由都定义在这个Handler上,也可以理解用定义在UserHandler上的方法来作为对应路由的处理逻辑。

package web

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

type UserHandler struct {
}

func (c *UserHandler) SignUp(ctx *gin.Context) {
	ctx.String(http.StatusOK, "hello,你在注册")
}

func (c *UserHandler) Login(ctx *gin.Context) {
	ctx.String(http.StatusOK, "hello,你在登录")
}

func (c *UserHandler) EditUser(ctx *gin.Context) {
	ctx.String(http.StatusOK, "hello,你在编辑")
}

func (c *UserHandler) UserProfile(ctx *gin.Context) {
	ctx.String(http.StatusOK, "hello,你在查看")
}

func (c *UserHandler) RegisterRoutes(server *gin.Engine) {
	ug := server.Group("/users")//分组路由
	ug.POST("/signup", c.SignUp)
	ug.POST("/login", c.Login)
	ug.POST("/edit", c.EditUser)
	ug.GET("/profile", c.UserProfile)
}

package main

import (
	"awesomeProject/src/internal/web"
	"github.com/gin-gonic/gin"
)

func main() {
	// 1.创建路由
	r := gin.Default()
	// 2.绑定路由规则,执行的函数
	c := &web.UserHandler{}
	c.RegisterRoutes(r)
	// 3.监听端口,默认在8080
	// Run("里面不指定端口号默认为8080")
	err := r.Run(":8000")
	if err != nil {
		return
	}
}

接下来,按照一般的流程,前端或者客户端就会调用我们的接口,例如(调用/users/signup接口实现注册功能)将相关的参数传递给后端,通常都是json格式的数据。

那现在,后端拿到相关的数据之后改如何处理呢?
通常分为三步:

  • 接收请求并校验
  • 调用业务逻辑处理请求
  • 根据业务逻辑处理结果返回响应

因此,我们的问题就是怎么在后端接收这个JSON数据?

接收请求数据:接收请求结构体

一般来说,我们都是定义一个结构体来接受数据。

func (c *UserHandler) SignUp(ctx *gin.Context) {
	//定义在方法内部的好处在于只有该方法能够使用SignUpReq
	type SignUpReq struct {
		Email           string `json:"email"`
		Password        string `json:"password"`
		ConfirmPassword string `json:"confirmPassword"`
	}
	ctx.String(http.StatusOK, "hello,你在注册")
}

接收请求数据:Bind方法

Bind方法是Gin里面最常用的用于接收请求的方法。
Bind方法会根据HTTP请求的Content-Type来决定怎么处理。比如我们的请求是JSON格式,Content-Type是application/json,那么Gin就会使用JSON来反序列化。
如果Bind方法发现输入有问题,它就会直接返回一个错误响应到前端。这句话怎么理解呢?例如,我们定义的email是string类型,如果前端传过来一个整型的话,那么gin就会直接返回一个400错误码给前端。

func (c *UserHandler) SignUp(ctx *gin.Context) {
	//定义在方法内部的好处在于只有该方法能够使用SignUpReq
	type SignUpReq struct {
		Email           string `json:"email"`
		Password        string `json:"password"`
		ConfirmPassword string `json:"confirmPassword"`
	}
	var req SignUpReq
	if err := ctx.Bind(&req); err != nil {
		return
	}
	//ctx.String(http.StatusOK, "hello,你在注册")
	ctx.JSON(200, gin.H{
		"msg": "hello,你在注册",
	})
}

校验请求

校验请求无可避的需要使用到正则表达式,一般我们获取到参数之后都会对参数进行校验要求其符合一定的格式然后才允许入库。这里就涉及到相关的业务逻辑了,我们暂时抛开不说。
正则匹配库推荐使用一个开源的正则匹配库:https://github.com/dlclark/regexp2,官方自带的正则表达式笔者查阅了一些资料好像是不支持一些语法的。

跨域问题

目前大多数的web框架,都提供了CORS的解决方案。Gin里面提供了一个middleware来解决跨域问题。
执行下面命令即可在代码中使用。

go get github.com/gin-gonic/contrib

熟悉Android中okhttp框架的同学可以用拦截器来理解middleware,所有的请求都会经过这些middleware。所以适合解决一些所有业务都关心的东西。

func (c *UserHandler) RegisterRoutes(server *gin.Engine) {
	//需要在POST或者GET方法之前调用,无论接口访问成功或失败middleware都会执行
	server.Use(
		func(context *gin.Context) {
			fmt.Println("第一个 middleware")
		}, func(context *gin.Context) {
			fmt.Println("第二个 middleware")
		}, cors.New(cors.Config{
			AllowCredentials: true,//是否允许带上用户认证信息(比如cookie)
			AllowedHeaders:   []string{"Content-Type"},//业务请求中可以带上的头
			AllowOriginFunc: func(origin string) bool {//哪些来源是允许的
				println("origin is " + origin)
				if strings.HasPrefix(origin, "http://localhost") {
					return true
				}
				return true
			},
			MaxAge: 12 * time.Hour,
		}))
	ug := server.Group("/users") //分组路由
	ug.POST("/signup", c.SignUp)
	ug.POST("/login", c.Login)
	ug.POST("/edit", c.EditUser)
	ug.GET("/profile", c.UserProfile)

}

在这里插入图片描述

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

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

相关文章

国标视频云服务EasyGBS国标平台进行内网映射两个公网设备配置的详细步骤

国标视频云服务EasyGBS支持设备/平台通过国标GB28181协议注册接入,并能实现视频的实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。平台部署简单、可拓展性强,支持将接入的视频流进行全终端、全平台分发,分发的视频…

无涯教程-PHP - 标量函数声明

在PHP 7中,引入了一个新函数,即标量类型声明。标量类型声明有两个选项- Coercive - 强制性是默认模式。Strict - 严格模式必须明确提示。 可以使用上述模式强制执行以下类型的函数参数- intfloatbooleanstringinterfacesarraycallable 强制模…

686. 重复叠加字符串匹配

686. 重复叠加字符串匹配 原题链接:完成情况:解题思路:参考代码:__686重复叠加字符串匹配__暴力解法__直接调用函数__686重复叠加字符串匹配__KMP算法 原题链接: 686. 重复叠加字符串匹配 https://leetcode.cn/prob…

vue 简单实验 自定义组件 综合应用 传参数 循环

1.代码 <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"todo-list-app"><ol><!--现在我们为每个 todo-item 提供 todo 对象todo 对象是变量&#xff0c;即其内容可以是动态的。…

Python Pandas 提取csv数据再合并

文章目录 需求思路&#xff1a;步骤伪代码 需求 从不同的csv文件中提取相同的列&#xff0c;然后合并成一个csv 假设有这样一张csv&#xff0c; column A&#xff0c; B&#xff0c; C, D 的数据分别来自a.csv, b.csv, c.csv, d.csv指定的某一列数据。 Title 列的Items是之前…

【自动驾驶】TI SK-TDA4VM 开发板上电调试,AI Demo运行

1. 设备清单 TDA4VM Edge AI 入门套件【略】USB 摄像头(任何符合 V4L2 标准的 1MP/2MP 摄像头,例如:罗技 C270/C920/C922)全高清 eDP/HDMI 显示屏最低 16GB 高性能 SD 卡连接到互联网的 100Base-T 以太网电缆【略】UART电缆外部电源或电源附件要求: 标称输出电压:5-20VDC…

无线路由器实现网络接入

目录 简介 1. 常见的接人互联网方式及设备 2.常见的接入互联网方式比较 2.2接入互联网设备 简介 随着IT技术的不断发展&#xff0c;一些中小型企业和家庭用户对网络带宽的需求越来越高。而传统的接入互联网方式虽然价格便宜&#xff0c;但是其稳定性受线路等其他因素影响。因…

轻松搭建远程Node.js服务端,让你的应用在公共网络中畅行无阻!

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

「2024」预备研究生mem-带绝对值的一次与二次不等式方程和不等式图像

一、带绝对值的一次与二次不等式&方程和不等式图像 代入特殊值 带绝对值的方程不等式&#xff1a; 二、课后题

solidity0.8.0的应用案例9:代理合约

代码由OpenZeppelin的Proxy合约简化而来。 代理模式 Solidity合约部署在链上之后,代码是不可变的(immutable)。这样既有优点,也有缺点: 优点:安全,用户知道会发生什么(大部分时候)。坏处:就算合约中存在bug,也不能修改或升级,只能部署新合约。但是新合约的地址与…

Mesa 23.2 开源图形栈现已可供下载

导读作为 Mesa 23 系列的第二个重要版本&#xff0c;Mesa 23.2 开源图形栈现已可供下载&#xff0c;它为 AMD GPU 的 RADV Vulkan 驱动程序带来了新功能&#xff0c;改进了 Linux 游戏&#xff0c;并新增了 Asahi 功能。 Mesa 23.2 的亮点包括 Asahi 上的 OpenGL 3.1 和 OpenGL…

GC面临的困境,JVM是如何解决跨代引用的?

本文已收录至GitHub&#xff0c;推荐阅读 &#x1f449; Java随想录 微信公众号&#xff1a;Java随想录 原创不易&#xff0c;注重版权。转载请注明原作者和原文链接 文章目录 跨代引用问题记忆集卡表写屏障写屏障的伪共享问题 前面我们讲了可达性分析和根节点枚举&#xff0c…

你真的了解四种内部类吗

作者简介&#xff1a; zoro-1&#xff0c;目前大一&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; 内部类 实例内部类注意事项 静态内部类注意事项 局…

联发科雄起,生成式AI将可在手机本地运行,天玑9300“大放异彩”

据报道&#xff0c;高通和联发科都计划在即将推出的旗舰手机上集成设备端生成式人工智能功能。这意味着用户将能够在手机上使用先进的语言模型技术。 高通选择与Meta合作&#xff0c;将其最新的语言模型Llama 2&#xff08;LLM&#xff09;引入他们的设备&#xff0c;而联发科则…

TCP最大连接数问题总结

最大TCP连接数量限制有&#xff1a;可用端口号数量、文件描述符数量、线程、内存、CPU等。每个TCP连接都需要以下资源&#xff0c;如图所示&#xff1a; 1、可用端口号限制 Q&#xff1a;一台主机可以有多少端口号&#xff1f;端口号与TCP连接&#xff1f;是否能修改&#x…

编程锦囊妙计——快速创建本地Mock服务

点击上方&#x1f446;蓝色“Agilean”&#xff0c;发现更多精彩。 前情提要 在本系列上一篇文章《全文干货&#xff1a;打破前后端数据传递鸿沟&#xff0c;高效联调秘笈》中我们分享了使用Zod这一运行时类型校验库来对后端服务响应结果进行验证达到增加项目质量的方式。 这次…

TypeError: div() got an unexpected keyword argument ‘rounding_mode’

报错代码&#xff1a;torch.div(…, …, rounding_mode“floor”) mask_idx torch.div(idx, self.instance_classes, rounding_mode“floor”) 报错原因&#xff1a; rounding_mode在torch1.8才引入 https://github.com/mit-han-lab/torchsparse/pull/126 torch.div()方法的…

生信豆芽菜-信号转导通路相关评分的计算

网址&#xff1a;http://www.sxdyc.com/gradeSigna 1、数据准备 表达谱数据&#xff0c;行为基因&#xff0c;列为样本 2、提交后&#xff0c;等待运行成功即可下载 当然&#xff0c;如果不清楚数据是什么样的&#xff0c;可以选择下载我们的示例数据&#xff0c;也可以关…

跨境出海:如何轻松应对多账号管理

在如今的跨境电商时代&#xff0c;成功经营一个线上店铺不再仅仅需要商品和服务&#xff0c;还需要精通广告投放、营销策略等多个领域。 然而&#xff0c;老练的电商从业者知道&#xff0c;如果不重视平台账号的管理方法&#xff0c;可能会导致店铺或营销账号被关联&#xff0…

NO.06 自定义映射resultMap

1、前言 在之前的博客中&#xff0c;实体类的属性名和数据库表的字段名是一致的&#xff0c;因此能正确地查询出所需要的数据。当实体类的属性名与数据库表的字段名不一致时&#xff0c;会导致查询出来的数据为空指针。要解决这个问题就需要使用resultMap自定义映射。 使用的…