Gin框架入门级教程与实践
Gin是一个用Go语言编写的高性能Web框架,它简洁、快速,并具有良好的路由和中间件支持。
Gin框架入门级教程与实践
为什么使用Gin
我们使用Gin的原因很直接也很简单,那就是Gin很强大也很简单。Gin框架具有如下的有点:
- 高性能:Gin框架使用了基于Radix树的路由匹配算法,使得路由查找非常快速。同时,Gin框架基于HTTP标准库进行开发,具有低内存占用和高并发处理能力。
- 简单易用:Gin框架提供了简洁的API和易于理解的代码结构,使得开发者能够快速上手并编写清晰、可维护的代码。
- 路由和中间件支持:Gin框架提供了灵活的路由定义方式,支持参数路由、分组路由等。同时,Gin框架内置了丰富的中间件支持,如日志、认证、CORS等,可以方便地实现各种功能和扩展需求。
- JSON解析和输出:Gin框架内置了强大的JSON解析和输出功能,可以方便地处理请求数据和生成响应。同时,Gin框架还支持其他格式的数据解析和输出,如XML、YAML等。
- 插件生态丰富:Gin框架有着活跃的社区和丰富的插件生态,可以方便地集成其他常用库和组件,如数据库ORM、缓存库、验证库等。
这些看一下就好,以后会体会到Go的高并发和JSON解析等强大功能的。
Gin框架的入门
下载Gin依赖
执行以下命令,下载和安装Gin依赖:
1 | go get -u github.com/gin-gonic/gin |
以下指令会把Gin安装在GOPATH里面的src文件夹中。
第一个Gin应用
我们先写一个Gin应用,打开Gin的世界。新建一个main.go文件,敲进去这样的代码:
1 | package main |
然后运行一下:
1 | go run main.go |
打开浏览器,输入:localhost:8888/hello
,结果返回为"message":"Veni"
,第一个Gin应用完美运行。
代码解析
package和import就不说了,从main函数开始。
1 | r := gin.Default() |
这一段代码用来创建一个默认的Gin引擎的实例并赋值给r,该实例已经配置了一些常用的中间件和默认的设置,比如默认使用Logger中间件用于记录请求日志,默认使用Recovery中间件用于恢复panic。还有默认的错误信息处理,默认请求路由器等等。
1 | r.GET("/hello", func(c *gin.Context) { |
r.GET()用于创建一个GET请求的处理函数,请求的路由是”/hello”,然后绑定了一个处理函数func。func函数的参数是c *gin.Context
,这是Gin框架里面的上下文对象,它封装了每个http请求的信息和操作方法,用于处理请求和响应。为什么要使用指针*
呢?因为这里面需要对这个上下文进行修改,因此采用指针传递才能在函数中修改变量的值。Gin.Context有许多用法,比如:
c.Request
:获取原始的 http.Request 对象。c.Writer
:获取原始的 http.ResponseWriter 对象。c.Param(key)
:获取路由参数值。c.Query(key)
:获取查询参数值。c.PostForm(key)
:获取表单参数值。c.JSON(code int, obj interface{})
:以 JSON 格式返回数据。c.HTML(code int, name string, data interface{})
:渲染 HTML 模板并返回。c.Set(key string, value interface{})
:设置上下文的键值对。c.Get(key string) interface{}
:获取上下文中的值。
所以,上面的c.JSON的作用就是以JSON格式返回数据,函数的第一个参数是整形返回码,interface可以是任意类型的对象。
gin.H{}是Gin框架中用来创建JSON或HTML相应的方式,可以创建一个 map [string] interface类型的对象。使用方法如下:
1 | data := gin.H{ |
在实际开发中,一般的返回JSON都命名成data,符合前后端开发的习惯。
Gin项目结构
Gin的项目结构可以是因人而异的。Go语言相互调用包的过程很简单,公有变量和私有变量只需要使用大小写区分。受到MVC架构的影响,我一般将项目组织成如下的结构:
1 | - main.go |
- main文件是程序的入口,用于完成初始化,启动Gin等操作;router用于配置路由信息,包括对应路由的处理函数。
- controller目录为控制器层,用于处理路由对应的请求。
- model目录是模型层,对应着数据库的一个关系或者自建的实体模型。
- middleware是中间件层,用于完成权限认证等操作。
- service层存放的是业务逻辑的相关代码,以及调用其他服务或API的代码,可以将DB和Redis等操作代码也放在这一文件夹中。
- test是测试目录,用于完成单元测试等工作。
在项目的实际开发中,推荐使用的命名方法是:公有类型名和方法名使用大驼峰,私有类型和方法、目录和文件名使用小驼峰。
Gin项目结构逐层解析
现在你已经能够启动Gin框架的hello world,并且也了解了Gin的项目结构。下面我们将逐个实现上述结构,让萌新也可以拥有一个完整的项目框架经验。
package main
main.go
前文中我们直接在main函数处理了一个GET请求,但是实际开发中是绝对不会把处理函数写在main函数里面的。main函数主要做两件事情:初始化环境和启动Gin。所以,一个简单的main.go文件如下:
1 | func main() { |
router.go
初始化引擎一句之前已经解析过了,下面讲讲InitRouter(r)。这个函数我们写在router.go这个文件中,用于处理路由和相关请求。比如下面的这个文件:
1 | func InitRouter(r *gin.Engine) { |
- 函数的参数需要带指针*,不然在主函数中调用是不会改变r的值的。
- r.Static用于注册静态文件的路径,比如某些HTML以及图片等,将其指向本地的public文件夹。
- 使用r.Group注册路由组,使用路由组可以统一注册中间件,同时也符合树形结构路由的要求。
- router.POST则指定了一个路径下的POST请求及其处理函数(controller.Login)。此时的路径必须加上路由组的路径,即完整的路径为:
/api/user/login/
。
config.yaml
该文件用于处理所有重要的配置,比如数据库,Redis等等。使用yaml记录配置十分简洁,可以将字段一一对应到某个go语言的结构体中,内容如下:
1 | database: |
每一个层级对应一个结构体,最小的层级对应结构体的一个字段。比如,用来存储database配置的两个结构体如下:
1 | type DatabaseConfig struct { |
package service
在主函数里面有一个初始化数据库的函数我们没有说,现在我们来讲一讲这个service.InitDatabase()
。这里需要一点gorm的基础,可以去看我的博客另一篇介绍gorm的文章。具体实现代码如下:
1 | var Db *gorm.DB |
DSN(Database Source Name)为数据库资源名称,用于gorm打开数据库并建立连接。后面对数据库的所有操作都可以通过Db这个变量来完成。
package model
这个目录存储了主要的结构体,比如model/user.go
:
1 | type User struct { |
使用gorm可以指定某一个属性对应的数据库表的字段,使用json则可以指定当该结构体序列化为json的时候的字段名。
package controller
下面是一个控制器的实例,用于处理路由器中已经指定的路由及其处理函数。这里以login为例,函数的具体实现如下,该函数写于controller/user.go
文件中
1 | // 登录功能 |
package middleware
这个包用来存放中间件的相关代码,简单的token验证中间件的实现方法如下:
1 | func QueryAuthMiddleWare() gin.HandlerFunc { |
这里假设处理函数面对的HTTP请求把token放在了Query的位置,则通过ctx.Query(“token”)即可获取到这个token值。这里使用Redis查询是否存在该token从而完成权限鉴定功能,具体实现在函数service.IsTokenExist(token)
中,这里就不给出详细代码了,可以自行到github仓库里面看。
package utils
这里存放一些代码中可能会使用到的工具函数,比如日期,时间转换等等。下面是一个日期转换的工具:
1 | type CustomTime struct { |
这个函数可以把日期序列化为YYYY-MM-DD hh-mm-ss
的形式。
package test
单元测试
这个包里面的函数用于开展单元测试,单元测试是软件开发中的一种测试方法,旨在验证代码中的最小可测试单元(通常是函数、方法或类)是否按预期工作。
- 对于需要测试的代码文件创建一个名为
*_test.go
的文件。 - 测试代码写成函数形式:
func TestXxx(t *testing.T)
- 初始化逻辑放在
TestMain(m *testing.M)
函数中,并且文件取名为main_test.go
测试文件
在test目录下,一般需要包含如下文件:config.yaml,main_test.go,*_test.go(*代表任意匹配),config.yaml里面的配置填写测试环境配置,比如测试数据库。main_test.go完成对测试环境的初始化工作,比如:
1 | //main_test.go |
然后就可以一次写各个函数的单元测试函数了,下面是一个处理gin框架下的POST请求的一个单元测试函数:
1 | //user_test.go |
启动测试
由于本项目将main_test.go
文件放在了test包中,那么就不能直接运行go test指令来启动测试了,取而代之的是go test ./test,此时test目录相当于一个项目的根目录,会运行main_test.go
之后自动扫描其他的test文件中的测试函数,一次运行的结果如下:
这里返回了422编码,表明用户不存在,因为测试数据库中并没有这个用户记录。
总结
以上就是本次Gin框架的基础教程了,部分代码截自我的第一个go项目,大家可以到仓库里面看具体代码,如果对大家有帮助,不妨在github点个star或者给这篇文章点个赞。