【Go语言】Gin 框架教程

Gin 框架教程

1.第一个 Gin 程序

1.1 Gin 安装

# 执行执行如下操作即可,安装Gin前需要安装Go环境
go get -u -v github.com/gin-gonic/gin
# -v:打印出被构建的代码包的名字
# -u:已存在相关的代码包,强行更新代码包及其依赖包

1.2 Gin 项目创建

在一个空文件夹里新建文件 main.go,参考如下代码编写一个 Gin 程序。

// blog.euansu.cn
// main.go
package mainimport "github.com/gin-gonic/gin"func main() {r := gin.Default()r.GET("/", func(c *gin.Context) {c.String(200, "Hello, EuanSu")})r.Run() // listen and serve on 0.0.0.0:8080
}

运行 main.go 程序,如下图所示。

go run main.go

在这里插入图片描述

代码说明:

  1. 首先,r := gin.Default()这里生成了一个 Gin 引擎实例,用于处理 HTTP 请求,也即 WSGI 应用程序,这个实例会预先加载一些默认的中间件。
  2. r.GET("/", ...) 则是声明了一个路由,以及路由对应的函数方法。
  3. r.Run() 函数则是运行应用程序,默认的监听端口是 8080,也可以传入参数设置应用程序运行端口,例如 r.Run(":8888"),即应用运行在 8888 端口。

1.3 网站图标设置

这里使用一个 Gin 的中间件 github.com/thinkerou/favicon,使用同 gin 框架,首先是安装 github.com/thinkerou/favicon 库。

go get github.com/thinkerou/favicon

接下来,则是使用该中间件,代码如下所示:

// blog.euansu.cn
// main.go
package mainimport ("github.com/gin-gonic/gin""github.com/thinkerou/favicon"
)func main() {// 创建一个服务r := gin.Default()// 使用中间件r.Use(favicon.New("./static/favicon.ico"))// 路由函数r.GET("/", func(c *gin.Context) {c.String(200, "Hello, EuanSu")})r.Run() // listen and serve on 0.0.0.0:8080
}

项目运行后,就能够在浏览器中看到 favicon.ico 网站图标。

在这里插入图片描述

2.Gin 中的路由

2.1 路由语法

$router.$method("$router", $handlerFunction)
# router,Gin 引擎实例
# method,http路由方法,可选参数为:GET、POST、PUT、PATCH、DELETE、OPTIONS、HEAD以及能够处理任意类型的HTTP请求的Any和处理指定类型的HTTP请求的Match
# handlerFunction,路由函数,处理路由响应

示例如下:

router.GET("/path", handlerFunction) 								// 获取资源
router.POST("/path", handlerFunction) 								// 创建资源	
router.PUT("/path", handlerFunction) 								// 更新资源
router.DELETE("/path", handlerFunction) 							// 删除资源
router.PATCH("/path", handlerFunction) 								// 更新部分资源
router.OPTIONS("/path", handlerFunction) 							// 获取服务器支持的 HTTP 方法
router.HEAD("/path", handlerFunction) 								// 获取资源的头部信息
router.Any("/path", handlerFunction) 								// 处理任意类型的 HTTP 请求
router.Match([]string{"GET", "POST"}, "/path", handlerFunction) 	// 处理指定类型的 HTTP 请求

2.2 请求参数的处理

2.2.1 路由参数解析

参数包含在路由中,如 /user/:name,通过调用不同的 路由参数 传入不同的 name,如下所示:

r.GET("/user/:name", func(c *gin.Context) {name := c.Param("name")c.String(http.StatusOK, "%s, Welcome to your clicl.", name)
})

在这里插入图片描述

这里需要注意下,如果新增了路由,需要重启 Gin 程序,重启之后,再次访问路由地址,就能够正常解析路由参数了。

在这里插入图片描述

2.2.2 Query 参数解析

Query 参数 与上文的路由参数一样,参数都是路由的一部分,不同的是 Query 参数 是键值对的形式,查询参数通常位于URL的问号(?)之后,以键值对的形式出现,并且多个参数之间用与号(&)分隔。

r.GET("/users", func(c *gin.Context) {name := c.Query("name")c.String(http.StatusOK, "%s, Thank you for your click.", name)
})

在这里插入图片描述

也可以直接使用 URL 通过浏览器请求该接口。

在这里插入图片描述

2.2.3 POST 参数解析(form表单)

这里使用一个表单参数进行举例,如下所示,输入分数转化为及格、不及格的判断,代码如下所示。

package mainimport ("github.com/gin-gonic/gin""net/http""strconv"
)func evaluateScore(score int) string {if score >= 90 {return "优秀"} else if score >= 60 {return "及格"} else {return "不及格"}
}func main() {r := gin.Default()// POST参数解析// POSTr.POST("/form", func(c *gin.Context) {username := c.PostForm("username")// DefaultPostForm,只支持string类型,因此需要进行类型的转换scoreStr := c.DefaultPostForm("score", "0")score, err := strconv.Atoi(scoreStr)if err != nil {// 处理错误情况,例如当输入的值不是整数时c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid score"})return}result := evaluateScore(score)c.JSON(http.StatusOK, gin.H{"username": username, "score": score, "evaluation": result})})r.Run() // listen and serve on 0.0.0.0:8080
}
r.POST("/form", func(c *gin.Context) {username := c.PostForm("username")password := c.DefaultPostForm("password", "000000") // 可设置默认值fmt.Println(password)c.String(http.StatusOK, "%s, Thank you for your login.", username)
})

请求后端的接口,返回如下。

在这里插入图片描述

2.2.4 POST 参数解析(json)
package mainimport ("github.com/gin-gonic/gin""net/http""strconv"
)func evaluateScore(score int) string {if score >= 90 {return "优秀"} else if score >= 60 {return "及格"} else {return "不及格"}
}// 定义结构体,与JSON数据匹配
type Person struct {Username string `json:"username"`Score    int    `json:"score"`
}func main() {r := gin.Default()// 处理POST请求,接收JSON参数r.POST("/json", func(c *gin.Context) {var person Person// 绑定JSON到结构体if err := c.ShouldBindJSON(&person); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}result := evaluateScore(person.Score)c.JSON(http.StatusOK, gin.H{"username": person.Username, "score": person.Score, "evaluation": result})})r.Run() // listen and serve on 0.0.0.0:8080
}

请求后端的接口,返回如下。

在这里插入图片描述

2.3 路由处理

2.3.1 重定向
r.GET("/redirect", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "/")
})

如下所示,当后端收到 /redirect 路由的请求,会重定向至 /

在这里插入图片描述

2.3.2 分组路由

分组路由主要是为了处理路由前缀一致的情况,例如有一组路由前缀都是 /api/v1 开头,通过分组路由就能够简化路由的定义,也可以更好的实现路由的权限控制,例如将需要登录的路由放到同一分组中。代码示例如下:

// 默认的路由方法
defaultHandler := func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"path": c.FullPath(),})
}// group: v1
v1 := r.Group("/v1")
{v1.GET("/posts", defaultHandler)v1.GET("/series", defaultHandler)
}
// group: v2
v2 := r.Group("/v2")
{v2.GET("/posts", defaultHandler)v2.GET("/series", defaultHandler)
}

请求不同的路由地址,均能够得到正常的响应。

在这里插入图片描述

在这里插入图片描述

3.RESTful API

RESTful API 具体概念可以查看 https://blog.euansu.cn/post/djangorestframework/ 这篇文章中关于 RESTful API 的相关介绍 。

使用 Go 语言能够快速的实现 RESTful API,实现如下:

r.GET("/user", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "get user"})
})
r.POST("/user", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "post user"})
})
r.PUT("/user", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "put user"})
})
r.DELETE("/user", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "delete user"})
})

使用 Apifox 等接口测试工具测试,应用程序能够根据使用的 HTTP 请求方式的不同而使用不同的函数进行处理。

  • GET 请求

    在这里插入图片描述

  • POST 请求

    在这里插入图片描述

  • PUT 请求

    在这里插入图片描述

  • DELETE 请求

    在这里插入图片描述

如上测试所示,Gin 框架能够快速、简洁的实现 RESTful API

4.响应页面

可以通过以下方式,先加载静态页面到 Gin 应用程序中。

// 加载静态页面
r.LoadHTMLGlob("templates/*")
// 加载指定的静态页面(不推荐)
r.LoadHTMLFiles("templates/index.html")

路由函数

r.GET("/", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", gin.H{"msg": "index.html", "path": "/"})
})

打开浏览器,访问 Gin/ 路由,显示如下。

在这里插入图片描述

5.中间件

首先是在项目中,声明一个中间件方法 myHandler(),如下是 myHandler() 的代码方法。

func myHandler() gin.HandlerFunc {return func(c *gin.Context) {// 设置中间件的值c.Set("usersession", "xxx")if c.Request.URL.Path == "/" {// 阻止fmt.Println("阻止")c.Abort()}// 放行fmt.Println("放行")c.Next()}
}

Gin 应用程序中使用这个中间件。

func main() {// 创建一个服务r := gin.Default()// 使用中间件r.Use(myHandler())...r.Run() // listen and serve on 0.0.0.0:8080
}

实际测试效果如下:

  • 请求 / 路由,后端返回为空。

    在这里插入图片描述

  • 请求其他的路由,则不受影响,就如我们在中间件方法所写的判断一样,仅仅只是拦截了 / 的路由请求。

    在这里插入图片描述

6.数据库

Gin 项目中使用数据库,涉及以下操作:

  1. 安装数据库驱动和 ORM 库,安详需要使用的数据库驱动和 ORM 库,常见的 ORM 库是 GORM,支持 MySQLPostgreSQLSQLite 等数据库。
  2. 配置数据库的连接信息,需要在 Gin 项目配置中配置数据库连接,通常是 main.go 或者单独的配置文件。
  3. 初始化数据库,在项目启动的时候,进行数据库连接的初始化。
  4. 项目中使用数据库, 在路由关联的函数中使用数据进行增删改查的操作。

6.1 安装数据库驱动和 ORM 库

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

6.2 配置数据库的连接信息

main.go 文件中配置数据库的连接信息。

// 数据库连接信息
dsn := "username:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
var err error// 连接数据库
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {log.Fatalf("无法连接数据库: %v", err)
}

6.3 数据库初始化

使用 gorm 库,定义数据库模型,在 main.go 文件中添加 AutoMigrate 方法,进行数据库的迁移操作。

// 定义一个全局的数据库连接变量
var db *gorm.DB// User 定义数据库模型
type User struct {ID       uint   `json:"id" gorm:"primaryKey"`Username string `json:"username"`Email    string `json:"email"`
}func main() {// 创建一个服务r := gin.Default()// 使用中间件r.Use(favicon.New("./static/favicon.ico"))r.Use(myHandler())// 加载静态页面r.LoadHTMLGlob("templates/*")// 数据库连接信息dsn := "username:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"var err error// 连接数据库db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {log.Fatalf("无法连接数据库: %v", err)}// 自动迁移数据库db.AutoMigrate(&User{})r.Run() // listen and serve on 0.0.0.0:8080
}

项目启动如下,项目启动后,执行 AutoMigrate 方法。

在这里插入图片描述

连接配置的数据库,发现 AutoMigrate 初始化生成的表,数据库迁移操作成功。

在这里插入图片描述

6.4 数据库使用

如下是获取用户列表和创建用户的两个函数方法。

// 获取用户列表的处理函数
func getUsers(c *gin.Context) {var users []Userresult := db.Find(&users)if result.Error != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})return}c.JSON(http.StatusOK, users)
}// 创建用户的处理函数
func createUser(c *gin.Context) {var user Userif err := c.ShouldBindJSON(&user); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}result := db.Create(&user)if result.Error != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})return}c.JSON(http.StatusOK, user)
}

main.go 中添加路由函数,如下所示:

// 定义路由和处理函数
r.GET("/users", getUsers)
r.POST("/users", createUser)

进行路由请求,如下所示:

  • POST 请求进行用户的创建。

    在这里插入图片描述

  • GET 请求获取用户信息。

    在这里插入图片描述

数据库操作的完整代码为:

// blog.euansu.cn
// main.go
package mainimport ("fmt""github.com/gin-gonic/gin""github.com/thinkerou/favicon""gorm.io/driver/mysql""gorm.io/gorm""log""net/http"
)func myHandler() gin.HandlerFunc {return func(c *gin.Context) {// 设置中间件的值c.Set("usersession", "xxx")if c.Request.URL.Path == "/" {// 阻止fmt.Println("阻止")c.Abort()}// 放行fmt.Println("放行")c.Next()}
}// 定义一个全局的数据库连接变量
var db *gorm.DB// User 定义数据库模型
type User struct {ID       uint   `json:"id" gorm:"primaryKey"`Username string `json:"username"`Email    string `json:"email"`
}func main() {// 创建一个服务r := gin.Default()// 使用中间件r.Use(favicon.New("./static/favicon.ico"))r.Use(myHandler())// 加载静态页面r.LoadHTMLGlob("templates/*")// 数据库连接信息dsn := "username:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"var err error// 连接数据库db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {log.Fatalf("无法连接数据库: %v", err)}// 自动迁移数据库db.AutoMigrate(&User{})// 定义路由和处理函数r.GET("/users", getUsers)r.POST("/users", createUser)// 路由函数r.GET("/", func(c *gin.Context) {//c.String(200, "Hello, EuanSu")c.HTML(http.StatusOK, "index.html", gin.H{"msg": "index.html", "path": "/"})})r.GET("/home", func(c *gin.Context) {//c.String(200, "Hello, EuanSu")c.HTML(http.StatusOK, "index.html", gin.H{"msg": "index.html", "path": "/home"})})r.Run() // listen and serve on 0.0.0.0:8080
}func getUsers(c *gin.Context) {var users []Userresult := db.Find(&users)if result.Error != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})return}c.JSON(http.StatusOK, users)
}func createUser(c *gin.Context) {var user Userif err := c.ShouldBindJSON(&user); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}result := db.Create(&user)if result.Error != nil {c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()})return}c.JSON(http.StatusOK, user)
}

7.相关链接

[1] Go Gin 简明教程 https://geektutu.com/post/quick-go-gin.html

[2] 【【狂神说】Gin框架一小时上手 | 快速转型GoWeb开发 | Go语言零基础教程】 https://www.bilibili.com/video/BV1Rd4y1C7A1/?share_source=copy_web&vd_source=5fdcc6213ac2d30f16a78fe5d6e8df4d

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

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

相关文章

框架的使用

什么是框架? 盖房子,框架结构 框架结构就是房子主体,基本功能 把很多基础功能已经实现(封装了) 框架:在基础语言之上,对各种基础功能进行封装,方便开发者,提高开发效…

JavaFX 图像视图

JavaFX ImageView 控件可以在 JavaFX GUI 中显示图像。ImageView 控件必须添加到场景图中才能可见。JavaFX ImageView 控件由类表示 javafx.scene.image.ImageView。 创建一个 ImageView 通过创建类的实例来创建 ImageView 控件实例ImageView。类的构造函数ImageView需要一个…

02 设计过程概述

02 设计过程概述 2-1 设计需求2-2 飞机设计的各个阶段2-2-1 概念设计2-2-2 初步设计2-2-3 详细设计 2-3 飞机概念设计的流程2-4 集成产品开发和飞机设计2-5 补充2-5-1 布局设计(Configuration Design)关键任务:作用和重要性:使用领…

ARIMA模型与ARIMA-GARCH模型预测时间序列

上世纪 70 年代初,Ljung 等人提出 ARIMA 模型,又称求和自回归移动平均模型。其思想 是针对于非平稳时间序列进行数学建模,将其通过差分运算后 进行相关数据刻画 ,变为一个平稳的新序列,进而进行相关数据的刻画。 自 1…

Sping源码(九)—— Bean的初始化(非懒加载)— Bean的创建方式(自定义BeanPostProcessor)

序言 之前文章有介绍采用FactoryBean的方式创建对象,以及使用反射创建对象。 这篇文章继续介绍Spring中创建Bean的形式之一——自定义BeanPostProcessor。 之前在介绍BeanPostProcessor的文章中有提到,BeanPostProcessor接口的实现中有一个Instantiatio…

[文献解读]:斯坦福最新研究-HumanPlus:人形机器人跟踪和模仿人类

摘要 制造具有与人类相似外形的机器人的关键论点之一是,我们可以利用大量人类数据进行训练。然而,由于人形机器人感知和控制的复杂性、人形机器人与人类在形态和驱动方面仍然存在的物理差距,以及人形机器人缺乏从自我中心视觉学习自主技能的…

马克·雷伯特访谈:机器人的未来及波士顿动力的创新之路

引言 机器人技术作为现代科技的前沿领域,始终吸引着大量的关注与研究。波士顿动力公司作为这一领域的领军者,其创始人兼前CEO马克雷伯特(Marc Raibert)近日在主持人莱克斯弗里德曼(Lex Fridman)的播客节目…

如何用 ChatGPT DALL-E3绘画(10个案例)

如何用ChatGPT绘画——10个案例(附提示词) DALL•E 3可以在ChatGPT plus里直接使用了。 如果想免费使用,可以用新必应免费使用。 上次有个朋友问:DALL•E 3 有什么用。 这里用十个案例,来解释一下这个问题。 1.创…

爱心代码来喽

今天给大家分享一个爱心代码&#xff0c;送给我的粉丝们。愿你们天天开心&#xff0c;事事顺利&#xff0c;学业和事业有成。 下面是运行代码&#xff1a; #include<stdio.h> #include<Windows.h> int main() { system(" color 0c"); printf(&q…

对接钉钉Stream模式考勤打卡相关事件的指南

钉钉之前的accessToken是公司级别的&#xff0c;现在的accessToken是基于应用的&#xff0c;接口的权限也是基于应用的。所以第一步是在钉钉开放平台&#xff08;https://open-dev.dingtalk.com/&#xff09;创建一个应用。 创建好应用之后&#xff0c;因为我们后续还需要调用钉…

docker拉取镜像太慢解决方案

前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 创建daemon.json文件,输入以下信息 vim /etc/docker/daemon.json{"registry-mirrors": ["https://9cpn8tt6.mirror…

“Dream Machine“震撼登场!免费推出的AI电影级巨制在网络上引爆热潮

"巅峰初现&#xff01;视频AI新星‘梦幻制造者’华美登场&#xff01; 在视频生成技术的赛道上&#xff0c;Luma AI昨日骄傲地揭开了其旗舰创新——梦幻制造者&#xff08;Dream Machine&#xff09;的神秘面纱&#xff0c;凭借无与伦比的文本到视频及图像到视频转换技术…

【尚庭公寓SpringBoot + Vue 项目实战】看房预约管理(十三)

【尚庭公寓SpringBoot Vue 项目实战】看房预约管理&#xff08;十三&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】看房预约管理&#xff08;十三&#xff09;1、业务说明2、代码开发2.1、根据条件分页查询预约信息2.2、根据ID更新预约状态 1、业务说明 看房预约…

Python 踩坑记 -- 调优

前言 继续解决问题 慢 一个服务运行有点慢&#xff0c;当然 Python 本身不快&#xff0c;如果再编码不当那这个可能就是量级上的劣化。 整个 Code 主线逻辑 1700&#xff0c;各依赖封装 3000&#xff0c;主线逻辑也是很久远的痕迹&#xff0c;长函数都很难看清楚一个 if els…

设计通用灵活的LabVIEW自动测试系统

为了在不同客户案例中灵活使用不同设备&#xff08;如采集卡、Modbus模块&#xff09;且保持功能一致的LabVIEW自动测试系统&#xff0c;需要采用模块化的软件架构、配置文件管理、标准化接口和良好的升级维护策略。本文从软件架构、模块化设计、配置管理、升级维护、代码管理和…

Centos实现Mysql8.4安装及主主同步

8.4的Msyql在同步的时候与之前的版本有很大不同&#xff0c;这里记录一下安装流程 Mysql安装 官网下载 选择自己的版本&#xff0c;选第一个 复制下载链接 在服务器上创建一个msyql目录 使用命令下载,链接换自己的 wget https://dev.mysql.com/get/mysql84-community-relea…

Web前端项目-交互式3D魔方【附源码】

交互式3D魔方 ​ 3D魔方游戏是一款基于网页技术的三维魔方游戏。它利用HTML、CSS和JavaScript前端技术来实现3D效果&#xff0c;并在网页上呈现出逼真的魔方操作体验。 运行效果&#xff1a; 一&#xff1a;index.html <!DOCTYPE html> <html><head><…

绿色版DirectoryOpus功能强大且高度可定制的Windows文件管理器

Directory Opus&#xff08;通常简称为DOpus&#xff09;是一款功能强大且高度可定制的Windows文件管理器。它提供了许多超越Windows默认文件资源管理器&#xff08;Explorer&#xff09;的功能&#xff0c;使得文件和文件夹的管理变得更加高效和直观。以下是对Directory Opus的…

R进阶使用技巧

Introduction 分享一些R进阶使用的技巧&#xff0c;相当于是之前写的R语言学习的实践和总结了。 Online slide: https://asa-blog.netlify.app/R_tips_for_advanced_use_byAsa/R_tips.html 下载slide和相关的各种test文件: https://asa-blog.netlify.app/R_tips_for_advanced…

GTK tutorial 十三

Spin Buttons Spin Button用于让用户在一个范围内的数值中选择一个数字。它包含一个text entry box,并且在entry box旁边有用于上下翻的箭头按钮。entry box也能够直接被编辑。 下面举例说明其用法。 程序运行结果&#xff1a; /**spinbutton.c/ #include<stdio.h> #i…