大家好,欢迎来到IT知识分享网。
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 main import "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
代码说明:
- 首先,
r := gin.Default()
这里生成了一个Gin
引擎实例,用于处理HTTP
请求,也即WSGI
应用程序,这个实例会预先加载一些默认的中间件。 r.GET("/", ...)
则是声明了一个路由,以及路由对应的函数方法。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 main import ( "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 main import ( "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参数解析 // POST r.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 main import ( "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
项目中使用数据库,涉及以下操作:
- 安装数据库驱动和
ORM
库,安详需要使用的数据库驱动和ORM
库,常见的ORM
库是GORM
,支持MySQL
、PostgreSQL
和SQLite
等数据库。 - 配置数据库的连接信息,需要在
Gin
项目配置中配置数据库连接,通常是main.go
或者单独的配置文件。 - 初始化数据库,在项目启动的时候,进行数据库连接的初始化。
- 项目中使用数据库, 在路由关联的函数中使用数据进行增删改查的操作。
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 []User result := 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 User if 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 main import ( "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 []User result := 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 User if 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
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/148804.html