golang——Gin框架及路由介绍

ops/2024/12/12 6:27:26/

一. 框架介绍

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 mainimport ("net/http""github.com/gin-gonic/gin"
)func main() {//将应用切换到“发布模式”以提升性能gin.SetMode(gin.ReleaseMode)//创建路由r := gin.Default()//绑定路由规则,执行函数//gin.Context,封装了request和responser.GET("/", func(c *gin.Context) {c.String(http.StatusOK, "hello world")})//监听端口,默认绑定端口8080r.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里面,一个Web服务器被抽象成了Engnie。你可以在一个应用里面创建多个Engine实例,监听不同的端口。Engine承担了路由注册,接入中间件的核心职责。

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

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.2API参数

  • 可以通过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 mainimport ("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中的nameif err != nil {c.String(500, "上次图片错误")}//参数1为指定需要保存操作的文件,参数2为指定保存路径。c.SaveUploadedFile(file, file.Filename)//返回文件名c.String(http.StatusOK, file.Filename)})r.Run()
    

    }

演示:

上传特定文件:

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

package mainimport ("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 mainimport ("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 默认32MBr.MaxMultipartMemory = 8 << 20 * 2r.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 mainimport ("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.ppmy.cn/ops/141179.html

相关文章

http网络服务-swift-Alamofire

依赖库的github地址 http网络库 Alamofire 解json SwiftyJSON Swift Package Manager集成依赖库 https://github.com/Alamofire/Alamofire.githttps://github.com/emqx/CocoaMQTT.git使用 import Alamofire import SwiftyJSONvar http "http://xxxxxxxx" var p…

信息系统项目管理-里程碑范例

序号里程碑名称计划完成时间实际完成时间是否完成备注1项目计划确定2023.8.302023.8.25完成2需求说明书完成2023.10.302023.10.29完成3软件详细设计方案完成2023.11.132023.11.10完成4硬件详细设计方案完成2023.12.102023.12.12完成5提交系统测试报告2024.4.302024.4.28完成6提…

sql server 事务日志 大小

事务日志物理体系结构 数据库事务日志映射在一个或多个物理文件上。 从概念上讲&#xff0c;日志文件是一系列日志记录。 从物理上讲&#xff0c;日志记录序列被有效地存储在实现事务日志的物理文件集中。 每个数据库必须至少有一个日志文件。 虚拟日志文件 (VLF) SQL Serve…

XMOS将在CES 2025上展出多款由边缘AI驱动的创新音效、音频、识别和处理解决方案

全球智能物联网技术领导者暨匠心独到的半导体科技企业XMOS宣布&#xff1a;该公司将再次参加2025年国际消费电子展&#xff08;CES 2025&#xff09;&#xff0c;并将在本届CES上展出一系列由人工智能&#xff08;AI&#xff09;驱动的全新空间音效、语音捕获与降噪、音视频多模…

ceph基本概念

文章目录 1、传统存储与server san2、存储使用分类(存储表现的形式)1、块存储1、ceph怎么实现呢 2、文件系统存储1、ceph怎么实现 3、对象存储1、cpeh怎么实现 3、存储的架构分类1、集中式存储2、分布式存储 4、CEPH1、优点2、ceph哲学3、ceph技术4、ceph的全面优点 5、CEPH存储…

给我的小程序加了个丝滑的搜索功能,踩坑表情包长度问题

前言 最近在用自己的卡盒小程序的时候&#xff0c;发现卡片越来越多&#xff0c;有时候要找到某一张来看看笔记要找半天&#xff0c;于是自己做了一个搜索功能&#xff0c;先看效果&#xff1a; 怎么样&#xff0c;是不是还挺不错的&#xff0c;那么这篇文章就讲讲这样一个搜索…

23种设计模式之观察者模式

目录 1. 简介2. 代码2.1 Subject2.2 ConcreteSubject2.3 Observer2.4 ConcreteObserver2.5 Test &#xff08;测试&#xff09;2.6 运行结果 3. 优缺点4. 总结 1. 简介 观察者模式&#xff08;Observer Pattern&#xff09; 是一种行为设计模式。它定义了一种一对多的依赖关系…

最近邻搜索 - 经典树型结构 M-Tree

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 最近邻搜索的目标是从 N N N 个对象中&#xff0c;快速找到距离查询点最近的对象。根据需求的不同&#xff0c;该任务又分…