golang——Gin框架及路由介绍

news2024/11/19 1:55:34

一. 框架介绍

        Gin是一个轻量级的Go语言Web框架,它具有高性能和简洁的设计。由于其快速的路由匹配和处理性能,Gin成为Go语言中最受欢迎的Web框架之一。

        特点:

  • 快速和轻量:Gin框架的设计注重性能和效率,采用了一些优化措施,使其成为一个快速而轻量级的框架。
  • 路由和中间件:Gin提供了强大的路由功能,支持参数传递,路由分组等特性。同时,它支持中间件的使用,可以方便的在请求处理过程中执行一系列的操作,比如身份验证,日志记录等。
  • json解析:Gin内置了对json的解析和序列化支持,使得处理json数据变得简单而高效。
  • 支持插件:Gin允许开发者通过插件来扩展框架的功能,这样可以根据项目的需求进行灵活定制。

文档:

  • Github地址:https://github.com/gin-gonic/gin
  • 中文文档:https://gin-gonic.com/zh-cn/docs/

 二. 安装

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

  • 命令安装Gin
go get github.com/gin-gonic/gin@latest
  • 导入代码
import "github.com/gin-gonic/gin"

 三. 第一个Gin应用

package main

import (
	"net/http"

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

func main() {
	//将应用切换到“发布模式”以提升性能
	gin.SetMode(gin.ReleaseMode)
	//创建路由
	r := gin.Default()
	//绑定路由规则,执行函数
	//gin.Context,封装了request和response
	r.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, "hello world")
	})

	//监听端口,默认绑定端口8080
	r.Run(":8080")
}

代码解释:

  • gin.Default:创建一个Gin引擎。gin.Default()返回一个带有默认中间件的Gin引擎,包括Logger和Recovery中间件,用于日志记录和恢复。
  •  r.Get("/", func(c *gin.Context){...}):定义了一个GET方法的路由,当访问路径是"/"时,执行后面的回调函数。
  • c.String(http.StatusOK, "hello world"):在回调函数中,通过c.String方法返回一个字符串"hello world"并设置HTTP状态码为200 OK。
  • s.Run(":8080"):启动Web服务,监听在0.0.0.0:8080。如果不指定端口号,默认使用8080端口。此时,你可以通过浏览器或HTTP客户端访问http://localhost:8080,将会得到"hello world"的响应。

四. 应用举例

        以下项目都是使用Gin框架开发的:

  • gorush:Go 编写的通知推送服务器。
  • fnproject:容器原生,云 serverless 平台。
  • photoprism:基于 Go 和 Google TensorFlow 实现的个人照片管理工具。
  • krakend:拥有中间件的超高性能 API 网关。
  • picfit:Go 编写的图像尺寸调整服务器。
  • gotify:基于 WebSocket 进行实时消息收发的简单服务器。
  • cds:企业级持续交付和 DevOps 自动化开源平台。

五. Gin入门

  • gin.Engine

        在Gin里面,一个Web服务器被抽象成了Engnie。你可以在一个应用里面创建多个Engine实例,监听不同的端口。Engine承担了路由注册,接入中间件的核心职责。

        它组合了RouterGroup,RouterGroup才是实现路由功能的核心组件。

  • gin.Context

        gin.Context是Gin里面的核心类型。字面意思是"上下文",在Gin里面的核心职责是:

  • 处理请求
  • 返回响应 

六. 路由

        6.1 介绍

  • gin框架中采用的路由库是基于httprouter做的
  • 地址为:https://github.com/julienschmidt/httprouter
  •  支持Restful风格的API,意思是"表面层状态转化",是一个互联网应用程序的API设计理念:URL定位资源。
  • 可以创建路由组,为了管理相同的URL。
package main

import (
	"net/http"

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

func main() {
	//将应用切换到“发布模式”以提升性能
	gin.SetMode(gin.ReleaseMode)
	//创建路由
	//默认使用了两个中间件Logger(),Recovery()
	r := gin.Default()

	r.GET("/hello1", func(c *gin.Context) {
		c.String(http.StatusOK, "hello1")
	})
	r.GET("/hello2", func(c *gin.Context) {
		c.String(http.StatusOK, "hello2")
	})

	//路由组1
	v1 := r.Group("/v1")
	{
		v1.GET("/hellov1", func(c *gin.Context) {
			c.String(http.StatusOK, "hello v1")
		})
		v1.GET("hellov11", func(c *gin.Context) {
			c.String(http.StatusOK, "hello v11")
		})
	}

	//路由组2
	v2 := r.Group("/v2")
	{
		v2.GET("/hellov2", func(c *gin.Context) {
			c.String(http.StatusOK, "hello v2")
		})

		v2.POST("/hellov22", func(c *gin.Context) {
			c.String(http.StatusOK, "hello v22")
		})
	}

	//监听端口,默认绑定端口8080
	r.Run(":8080")
}

        6.2  API参数 

  • 可以通过Context的Param方法来获取API参数
package main

import (
	"fmt"
	"net/http"
	"strings"

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

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

	r.GET("/user/:name/*action", func(c *gin.Context) {
		name := c.Param("name")
		action := c.Param("action")

		fmt.Println(name, ":", action) //对于url /user/wy/aa 打印 wy : /aa
		//去除/
		action = strings.Trim(action, "/")
		c.String(http.StatusOK, name+" is "+action)
	})
	r.Run()
}

        6.3 URL参数

  • URL参数可以通过DefaultQuery()或Query方法获取
  • DefaultQuery()若参数不存在,返回默认值。Query()若参数不存在,返回空串。
package main

import (
	"net/http"

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

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

	r.GET("/user", func(c *gin.Context) {
		name := c.Query("name")
		action := c.DefaultQuery("action", "")

		c.String(http.StatusOK, name+" is "+action)
	})
	r.Run()
}

        6.4 表单参数

  • 表单传输参数为POST请求,http常见的传输格式为四种:

    • application/json

    • application/x-www-form-urlencode

    • application/xml

    • mulipart/form-data

  • 表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencode或form-data格式的参数。

POST请求的html代码:

<!--test.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="/form" method="post"
action="application/x-www-form-urlencoded">
用户名:<input type="text" name="username" placeholder="请输入你的用户名">
<br>密&nbsp;&nbsp;&nbsp;码:<input type="password" name="userpassword"
placeholder="请输入你的密码"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>

服务端代码

package main

import (
	"net/http"

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

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

	//设置HTML文件所在目录
	r.LoadHTMLGlob("./*.html")
	//设置GET方法路由,成功返回test.html文件
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "test.html", nil)
	})

	//设置POST方法路由
	r.POST("/form", func(c *gin.Context) {
		//设置没有传的参数的默认值
		types := c.DefaultPostForm("type", "post")
		username := c.PostForm("username")
		password := c.PostForm("userpassword")

		c.String(http.StatusOK, "username:%s, userpassword:%s, types:%s", username, password, types)
	})

	r.Run()
}

演示:

         6.5 上传文件

上传单个文件:

  • multipart/form-data格式用于上传文件
  • gin文件上传与原生的net/http方法类似,不同在于gin吧原生的request封装到了c.Request中。
package main

import (
	"net/http"

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

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

	//设置HTML文件所在目录
	r.LoadHTMLGlob("./*.html")
	//设置GET方法路由,成功返回test.html文件
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "test.html", nil)
	})

	//设置POST方法路由
	r.MaxMultipartMemory = 8 << 20 //限制上传最大尺寸
	r.POST("/upload", func(c *gin.Context) {
		//用于获取表单信息中file格式的参数,并且返回一个文件流
		file, err := c.FormFile("file") //html中的name
		if err != nil {
			c.String(500, "上次图片错误")
		}
		//参数1为指定需要保存操作的文件,参数2为指定保存路径。
		c.SaveUploadedFile(file, file.Filename)
		//返回文件名
		c.String(http.StatusOK, file.Filename)

	})

	r.Run()
}

 演示:

上传特定文件:

        有的用户上传文件需要限制文件的类型以及上传文件的大小,可以基于原生的函数写法自己写一个可以限制大小以及文件类型的上传函数。

package main

import (
	"net/http"

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

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

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

	r.POST("/upload", func(c *gin.Context) {
		_, header, err := c.Request.FormFile("file")
		if err != nil {
			c.String(405, "文件错误")
			return
		}

		if header.Size > 1024*1024*2 {
			c.String(406, "文件太大")
			return
		}

		if header.Header.Get("Content-Type") != "image/png" {
			c.String(407, "只允许上传图片")
			return
		}

		c.SaveUploadedFile(header, header.Filename)
		c.String(http.StatusOK, header.Filename)
	})

	r.Run()
}

上传多个文件:

package main

import (
	"fmt"
	"net/http"

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

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

	r.LoadHTMLGlob("./*.html")
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "test.html", nil)
	})
	//限制表单上传大小8MB 默认32MB
	r.MaxMultipartMemory = 8 << 20 * 2
	r.POST("/upload", func(c *gin.Context) {
		//用于获取multipart表单。当用户通过表单上传文件时,浏览器通常会将表单编码为multipart/form-data格式。
		form, err := c.MultipartForm()
		if err != nil {
			c.String(http.StatusBadRequest, fmt.Sprintf("get a %v", err))
			return
		}
		//获取所有文件
		files := form.File["files"]
		//遍历所有文件
		for _, file := range files {
			if err := c.SaveUploadedFile(file, file.Filename); err != nil {
				c.String(http.StatusBadRequest, fmt.Sprintf("upload get a %v", err))
				return
			}
		}
		c.String(http.StatusOK, fmt.Sprintf("upload %d files ok", len(files)))
	})

	r.Run()
}

         6.6 路由原理

        httprouter会将所有路由规则构造一棵前缀树。

        例如有root,and,as,at,cn,com

        6.7 路由拆分与注册

  • 基本的路由注册

         下面最基础的gin路由注册方式,使用于路由条目比较少的简单项目或者项目demo。

package main

import (
	"fmt"
	"net/http"

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

func sayHello(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"message": "hello go",
	})
}

func main() {
	r := gin.Default()
	r.GET("/hello", sayHello)
	if err := r.Run(); err != nil {
		fmt.Printf("startup server err : %v", err)
	}
}
  • 路由拆分成单独文件或包 

        当项目的规模增大后,就不适合继续在项目的main.go文件中实现路由注册相关逻辑了,我们会倾向于把路由部分的代码都拆分出来,形成一个单独的文件或包。

  • 形成单独文件

  • 形成独立的包 

  • 拆分成多个文件

        当业务规模继续膨胀,单独的一个router文件或包已经满足不了我们的需求了。 因为我们把所有的路由注册都写在一个SetRouter函数中的话会很复杂。

        我们可以将其拆分为多个文件。

  • 路由拆分到不同APP 

        有时候项目规模太大,那么我们就更倾向于把业务拆分的更加详细,例如把不同的业务代码拆分成不同的APP。

        因此我们在项目目录下单独定义一个app目录,用来存放我们不同业务线的代码文件,这样就很容易进行横向扩展。

目录结构:

app/blog:

代码如下: 

gin/app/shop: 

 gin/router/router.go

 gin/main.go

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

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

相关文章

暗黑4PTR怎么参与测试 暗黑4第五赛季怎么参加PTR测试教程

暗黑破坏神4作为暗黑破坏神系列的最新作品&#xff0c;自从2023年上线就受到了一众好评。游戏是动作冒险类角色扮演游戏&#xff0c;游戏的背景设定在一个腐化的圣休瑞亚大陆上&#xff0c;玩家们可以五种职业中选择自己喜爱的游戏进行游戏。 暗黑破坏神4第五赛季现在已经开启P…

时序约束(一):时钟的约束

目录 一、时钟约束的目的 二、约束工程项目 三、主时钟和生成时钟 四、主时钟约束 五、生成钟约束 一、时钟约束的目的 之前的文章对时序分析的基本原理做了介绍&#xff0c;我们会发现时序分析离不开时钟信号。对于时序分析工具来说同样如此&#xff0c;分析工具需要我…

谈谈你对AQS的理解

AQS概述 AQS&#xff0c;全称为AbstractQueuedSynchronizer&#xff0c;是Java并发包&#xff08;java.util.concurrent&#xff09;中一个核心的框架&#xff0c;主要用于构建阻塞式锁和相关的同步器&#xff0c;也是构建锁或者其他同步组件的基础框架。AQS提供了一种基于FIF…

《mysql》--mysql约束

数据库约束 有的时候数据库中的数据是有一定要求的&#xff0c;有些数据认为是合法数据&#xff0c;有些是非法数据&#xff0c;如果靠人工检查显然是不靠谱的&#xff1b; 数据库会自动的对数据的合法性进行校验检查目的就是&#xff0c;保证数据中能够避免被插入/修改一些非…

刷盘,还是不刷盘,是一个问题 | 架构师之路重启

前几个有个朋友留言&#xff0c;问我说最近两年公号发读书感悟&#xff0c;职场感悟&#xff0c;AI实践居多了&#xff0c;发架构思路类的内容少了。 最近准备重启架构思路类的内容&#xff0c;且会保持一如既往的风格&#xff1a; 1. 希望引发大家思考&#xff0c;多讨论&…

docker安装与入门使用(适用于小白)

总结&#xff1a;Docker 是一个开源的容器化平台&#xff0c;旨在使开发、部署和运行应用程序的过程更加简单和高效。Docker 使用操作系统级虚拟化在单个主机上运行多个独立的容器。每个容器包含应用程序及其所有依赖项&#xff0c;确保在不同环境中具有一致的运行表现。 下面…

贪心算法——加工木棍(C++)

上大学&#xff0c;一天是一天&#xff0c;两天也是一天。 ——2024年6月27日 之前考试周断更了&#xff0c;今天重新开始&#xff01; 题目描述 有n根木棍&#xff0c;已知每根木棍的长度和重量。这些木棍在木工机器上加工&#xff0c;机器准备加工木棍需要一些时间&#xf…

ABB机器人示教器死机时如何重置?

ABB机器人示教器死机时如何重置&#xff1f; 若遇到机器人示教器死机或卡顿现象时&#xff0c;可尝试将示教器重置&#xff0c;具体方法可参考以下内容&#xff1a; 如下图所示&#xff0c;首先将机器人控制柜断电关机&#xff0c; 如下图所示&#xff0c;同时按住快捷键&…

2024年水利工程与交通运输国际学术会议(ICWCET 2024)

全称&#xff1a;2024年水利工程与交通运输国际学术会议(ICWCET 2024) 会议网址: http://www.icwcet.com 会议时间: 2024/6/25 截稿时间&#xff1a;2024/6/15 会议地点: 天津 投稿邮箱&#xff1a;icwcetsub-conf.com 投稿标题&#xff1a;ICWCET 2024ArticleTEL。 ★会议简介…

目标检测系列(二)yolov1的全面讲解

目录 1、网络结构 2、检测原理 3、制作训练正样本方法 4、损失函数 5、前向推理 6、模型缺限 YOLO的全称是you only look once&#xff0c;指只需要浏览一次就可以识别出图中的物体的类别和位置。YOLO被称为Region-free方法&#xff0c;相比于Region-based方法&#xff0…

GNU、Unix、Linux、Makefile、GCC、GDB、GPL、CentOS 7、Ubuntu之间的关系

全文总结 早期&#xff0c;Unix系统作为一类强大的操作系统&#xff0c;在计算领域奠定了基础。然而&#xff0c;出于对软件自由的追求&#xff0c;Richard Stallman在1983年发起了GNU项目&#xff0c;旨在创建一个完全自由的、与Unix兼容的操作系统。GNU项目不仅倡议软件自由…

Web自动化元素定位之xpath定位【超详细】

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Web自动化常见的定位方式 为什么要学习定位 1.让程序操作指定元素&#xff0c;就必须先找到此元…

金升阳电源被制裁,广州顶源电源模块可以完美替换

广州顶源电子科技股份有限公司,座落于国家高新技术开发区---广州科学城&#xff0c;是一家集研发、生产、销售及服务于一体的DC-DC&#xff0c;AC-DC电源的生产厂家。 公司通过了IATF16949汽车认证及ISO9001:2015质量管理体系认证。拥有专家级研发团队&#xff0c;产品研发经过…

农村经济与科技杂志社农村经济与科技编辑部2024年第8期目录

视点 数字经济驱动农业产业链升级路径研究——以河南省为例 王媛媛; 1-4 城乡融合视角下农村集体产权制度改革研究 齐建丽; 4-7 农业生态系统结构美建设内涵及实现路径 张鹏程; 8-13《农村经济与科技》投稿&#xff1a;cnqikantg126.com 农户宅基地退出政策加权…

2024 最新推广服务 API 推荐,助力业务腾飞

在数字化营销的浪潮中&#xff0c;API 服务正以其强大的功能和高效的特性&#xff0c;成为企业和开发者们实现精准推广、优化营销效果的得力助手。2024 年的今天&#xff0c;各种创新的 API 服务层出不穷&#xff0c;为广告投放、数据洞察等领域带来了前所未有的机遇。在接下来…

华为开发者调试工具使用介绍(MDC)

MDC的开发过程的三大工具&#xff1a;MMC、MDS、Mind Studio&#xff0c;这三个工具完成了开发过程中的配置文件编写、代码编写以及AI模型的开发三个任务。除了开发&#xff0c;MDC还准备了两个调试工具&#xff0c;用于使用过程中数据的查看等。这一些调试工具分别对映射MDC中…

简化部署流程——无线UWB如何实现自标定?

一.什么是UWB信标自标定&#xff1f; UWB&#xff08;超宽带&#xff09;自标定是指在UWB系统中&#xff0c;基站或节点能够自动识别和确定自己的位置&#xff0c;无需外部干预或手动输入其地理位置信息。这种技术主要利用系统内部的信号测量和算法来自动计算节点之间的距离以…

数据交换的桥梁:深入探索JSON序列化和反序列化

目录 JSON序列化 一、查看JSON文件&#xff0c;设置数据模板类 ​编辑 二、Newtonsoft.Json下载 三、代码理解 1.创建BatteryList的实例 2.初始化Batterys属性 3.添加Battery对象到Batterys列表中 4.完整的代码如下 四、运行结果展示 JSON反序列化 序列化是将对象或…

如何通过待办工具提升个人效率 减轻压力提升效率的待办app

在快节奏的现代社会中&#xff0c;工作任务繁重&#xff0c;人们的压力日益增大。为了减轻压力并提升工作效率&#xff0c;我们急需找到一种有效的方法来管理日常任务。幸运的是&#xff0c;随着科技的进步&#xff0c;各种新兴工具应运而生&#xff0c;为我们提供了便捷的解决…

企业内部运营常用的API服务有哪些?

企业内部运营常用的API服务是现代企业管理和协作的关键工具之一。这些API服务提供了丰富的功能和工具&#xff0c;帮助企业提高内部运营效率、优化业务流程和加强团队协作。首先&#xff0c;企业内部通信和协作API服务是不可或缺的。通过这些API服务&#xff0c;企业可以建立内…