目录
一、Gin介绍
Gin是一个用Go编写的HTTPweb框架。它是一个类似于martini但拥有更好性能的API框架, 优于httprouter,速度提高了近 40 倍。 点击此处访问Gin官方中文文档。
二、安装
1、安装Gin
控制台输入
go get -u github.com/gin-gonic/gin
2、代码中导入
import"github.com/gin-gonic/gin"
3、简单示例,验证
新建文件main.go,内容如下。
package main
import("net/http""github.com/gin-gonic/gin")funcmain(){// 1.创建路由
r := gin.Default()// 2.绑定路由规则,执行的函数// gin.Context,封装了request和response
r.GET("/",func(c *gin.Context){
c.String(http.StatusOK,"hello World!")})// 3.监听端口,默认在8080// Run("")里面不指定端口号默认为8080
r.Run(":8000")}
运行后访问: http://localhost:8000/
三、渲染前端与配置跨域
1、渲染html模板
Gin支持加载HTML模板, 然后根据模板参数进行配置并返回相应的数据,本质上就是字符串替换。LoadHTMLGlob()方法可以加载模板文件(参数为待渲染的html模板文件,
如果参数为相对路径则为运行路径的相对路径
)。
a、 渲染单个文件
比如:
r.LoadHTMLGlob("web/index.html")
b、 渲染文件夹下的所有文件
比如:
r.LoadHTMLGlob("web/*")
c、 渲染文件夹下的所有html后缀的文件
比如:
r.LoadHTMLGlob("web/*.html")
2、定义模板分割
r.Delims("<<<",">>>")
第一个参数为:模板标签开始标记
第二个参数为:模板标签结束标记
3、渲染静态文件和目录
如果你需要引入静态文件需要定义一个静态文件目录
r.Static("/assets","./assets")
若assets的目录结构为
可以根据 http://localhost:8000/assets/img/home.jpg 访问指定资源
如果r为路由组,则需要在assets前拼接路由组的路径包括其前缀
4、重定向
// 重定向两种默认应支持的首页访问方式
router.GET("/",func(c *gin.Context){//重定向到/index.html
c.Redirect(302,"/index.html")})
router.GET("/index",func(c *gin.Context){//重定向到/index.html
c.Redirect(302,"/index.html")})
router.GET("/index.html",func(c *gin.Context){//返回渲染的html模板中的index.html
c.HTML(http.StatusOK,"index.html", gin.H{"baseUrl":"http://"+ host,})})
5、配置跨域
r.Use(Next())
Nex()函数
// 允许跨域funcNext() gin.HandlerFunc {returnfunc(c *gin.Context){
method := c.Request.Method
c.Header("Access-Control-Allow-Origin","*")
c.Header("Access-Control-Allow-Headers","Access-Control-Allow-Headers,Authorization,User-Agent, Keep-Alive, Content-Type, X-Requested-With,X-CSRF-Token,AccessToken,Token")
c.Header("Access-Control-Allow-Methods","GET, POST, DELETE, PUT, PATCH, OPTIONS")
c.Header("Access-Control-Expose-Headers","Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Allow-Credentials","true")// 放行所有OPTIONS方法if method =="OPTIONS"{
c.AbortWithStatus(http.StatusAccepted)}
c.Next()}}
四、路由相关
1、创建路由组
// 创建路由组// 根据需要,可以为这种多级的路由组:r.Group("/v1/user")
userApi:= r.Group("/user")// 创建用户// 匹配POST请求的 /user
userApi.POST("", userCreate)// 修改用户// 匹配PUT请求的 /user/1 但不会匹配 /user/ 或者 /user
userApi.PUT("/:id", userUpdate)// 获取用户// 匹配GET请求的 /user/1 但不会匹配 /user/ 或者 /user
userApi.GET("/:id", userGet)// 查询用户// 匹配GET请求的 /user/list
userApi.GET("/list", userQuery)// 删除用户// 匹配DELETE请求的 /user/1 但不会匹配 /user/ 或者 /user
userApi.DELETE("/:id", userDelete)
Restful风格的API
2、路由参数
a、api参数
通过Context的Param方法来获取api参数
例如:
userApi.GET("/:id/:name", userGet)
userGet函数为
funcuserGet(ctx *gin.Context){//api参数可以为单个或者多个也可以拼接多级//ctx.Param()函数获取时参数需要与api中的名称一致才能获取到
id := ctx.Param("id")
name:= ctx.Param("name")
ctx.JSON(http.StatusOK, gin.H{"data": id,"name":name})return}
可以根据 http://localhost:8000/user/1/admin 访问此接口
访问效果为:
b、url参数
通过Context的Query方法与DefaultQuery方法来获取url参数
例如:
userApi.GET("/list", userQuery)
userQuery函数为
funcuserQuery(ctx *gin.Context){//获取
id := ctx.Query("id")//获取,第二个参数为获取为空的默认值,如果参数不存在则放回第二个参数
name := ctx.DefaultQuery("name","user")
ctx.JSON(http.StatusOK, gin.H{"data": id,"name": name})return}
可以根据 http://localhost:8000/user/list 后面拼接查询参数,访问此接口
访问效果为:
c、表单参数
表单参数测试与观察请求效果需要安装postman
通过Context的PostForm方法来获取表单参数
例如:
userApi.POST("", userCreate)
userCreate函数为
funcuserCreate(ctx *gin.Context){
id := ctx.PostForm("id")
name := ctx.PostForm("name")
ctx.JSON(http.StatusOK, gin.H{"data": id,"name": name})return}
如图,访问此接口
效果为:
d、json参数
json参数测试与观察请求效果需要安装postman
通过Context的GetRawData或者ShouldBindJSON方法来获取表单参数
例如:
userApi.PUT("/:id", userUpdate)
userUpdate函数为
GetRawData方法
funcuserUpdate(ctx *gin.Context){// 注意:下面为了举例子方便,暂时忽略了错误处理
b,_:= ctx.GetRawData()// 从ctx.Request.Body读取请求数据// 定义map或结构体var m map[string]interface{}// 反序列化_= json.Unmarshal(b,&m)
ctx.JSON(http.StatusOK, gin.H{"data": m["id"],"name": m["name"]})return}
ShouldBindJSON方法
//先定义结构type User struct{
Id string`form:"id" json:"id" binding:"required"`
Name string`form:"name" json:"name" binding:"required"`}//函数实现funcuserUpdate(ctx *gin.Context){var user User
if err := ctx.ShouldBindJSON(&user); err ==nil{
ctx.JSON(http.StatusOK, gin.H{"data": user.Id,"name": user.Name})return}else{
ctx.JSON(http.StatusOK, gin.H{"err": err.Error()})return}}
如图,访问此接口
效果为:
e、参数绑定
为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中form表单、JSON、XML等参数到结构体中。
代码示例:
定义要获取的结构
type User struct{
Id string`form:"id" json:"id" binding:"required"`
Name string`form:"name" json:"name" binding:"required"`}
userCreate函数为
funcuserCreate(ctx *gin.Context){var user User
if err := ctx.ShouldBind(&user); err ==nil{
ctx.JSON(http.StatusOK, gin.H{"data": user.Id,"name": user.Name})return}else{
ctx.JSON(http.StatusOK, gin.H{"err": err.Error()})return}}
userUpdate函数为
funcuserUpdate(ctx *gin.Context){var user User
if err := ctx.ShouldBind(&user); err ==nil{
ctx.JSON(http.StatusOK, gin.H{"data": user.Id,"name": user.Name})return}else{
ctx.JSON(http.StatusOK, gin.H{"err": err.Error()})return}}
3、上传文件
一般都是post请求表单传参
例如:
userApi.POST("/upload", userUpload)
userUpload函数为
//先定义结构type FileUpload struct{
File *multipart.FileHeader `form:"file"`
Type string`form:"type"`}//函数实现funcuserUpload(ctx *gin.Context){var fileUpload FileUpload
if err := ctx.ShouldBind(&fileUpload); err ==nil{//获取运行路径
ex, err := os.Executable()if err !=nil{
ctx.JSON(http.StatusOK, gin.H{"err": err.Error()})return}//定义接收文件的存放地址
path := filepath.Dir(ex)+string(os.PathSeparator)+ fileUpload.File.Filename
//接收文件并保存到指定path
err = ctx.SaveUploadedFile(fileUpload.File, path)
ctx.JSON(http.StatusOK, gin.H{"data": path,"type": fileUpload.Type})return}else{
ctx.JSON(http.StatusOK, gin.H{"err": err.Error()})return}}
如图,访问此接口
效果为:
postman测试请求这个接口时,注意file字段的类型为file才能选择文件哦
五、中间件
1、统一注册中间件
对全局路由或者已注册的路由组统一注册中间件
r.Use(CheckToken())
2、单独注册中间件
userApi.POST("/upload",CheckToken(),userUpload)
3、中间件函数实现
funcCheckToken() gin.HandlerFunc {returnfunc(c *gin.Context){//验证不通过直接跳出//c.JSON(http.StatusBadRequest, gin.H{"msg": "need token"})//c.Abort()//return//验证通过继续
c.Next()}}
版权归原作者 我不是皮卡丘啊 所有, 如有侵权,请联系我们删除。