Golang中Gin框架的使用入门教程

目录
  • 安装与简单测试
  • 常见请求与分组请求
  • 获取参数 与 参数合法性验证
    • 获得query中参数
    • 获得multipart/urlencoded form中的参数
    • 模型绑定和参数验证
    • 自定义参数验证
  • 项目结构参考
  • Gin框架运行模式
  • Gin如何获取客户ip
  • Gin处理请求结果
    • 以String类型响应请求
    • 以Json格式响应请求
    • 以文件形式响应请求
    • 设置http响应头
    • Gin处理html模板
    • Gin访问静态资源文件
  • Gin处理Cookie操作
  • Gin文件上传
  • Gin中间件

官方地址:gin-gonic.com/docs/

安装与简单测试

下载并安装Gin包,并导入引用

$ go get -u github.com/gin-gonic/gin

//将gin引入到代码中
import "github.com/gin-gonic/gin"
//可选。如果使用诸如 http.StatusOK 之类的常量,则需要引入 net/http 包
import "net/http"

编写如下测试代码

package main

import "github.com/gin-gonic/gin"

func main() {
   r := gin.Default()
   r.GET("/ping", func(c *gin.Context) {
      c.JSON(200, gin.H{
         "message": "pong",
      })
   })
   r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

然后在浏览器中进行测试: http://localhost:8080 就可以访问到响应的请求。

常见请求与分组请求

下面展示几种其他 常规 请求方式

// 下面列出常用几种请求方式
r.GET("/someGet", handle)
r.POST("/somePost", handle)
r.PUT("/somePut", handle)
r.DELETE("/someDelete", handle)
r.PATCH("/somePatch", handle)
r.HEAD("/someHead", handle)
r.OPTIONS("/someOptions", handle)
r.Any("/any", handle)

**还可以对请求进行分组操作。 **

v1 := r.Group("/v1")
{
   v1.GET("/login", handle)
}
v2 := r.Group("/v2")
{
   v2.GET("/login", handle)
}

下面例子 是** 获得请求中path**

func main() {
   router := gin.Default()

   // 匹配/user/john
   router.GET("/user/:name", func(c *gin.Context) {
      name := c.Param("name")
      c.String(http.StatusOK, "Hello %s", name)
   })

   // 匹配/user/john/和/user/john/send
   router.GET("/user/:name/*action", func(c *gin.Context) {
      name := c.Param("name")
      action := c.Param("action")
      message := name + " is " + action
      c.String(http.StatusOK, message)
   })

   router.Run(":8080")
}

/user/:name/*action : 表示对后边路由全部模糊匹配。例如:/user/john/send/1 形式 action会匹配得到 name 是 john, action是 /send/1

获取参数 与 参数合法性验证

获得query中参数

func main() {
   router := gin.Default()

   // welcome?firstname=Jane&lastname=Doe
   router.GET("/user", func(c *gin.Context) {
      firstname := c.DefaultQuery("name", "kim") // 获取query中的name,没有的话就为kim
      lastname := c.Query("age")                 // 获取query中的age
      c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
   })
   router.Run(":8080")
}

获得multipart/urlencoded form中的参数

func main() {
   router := gin.Default()
   router.POST("/form_post", func(c *gin.Context) {
      message := c.PostForm("age")
      nick := c.DefaultPostForm("name", "kim")

      c.JSON(200, gin.H{
         "status":  "posted",
         "message": message,
         "nick":    nick,
      })
   })
   router.Run(":8080")
}

curl http://127.0.0.1:8080/form\_post -X POST -d 'name=john&age=25'

通过此curl发送post请求,即可获得表单中数据。

模型绑定和参数验证

基本用法

我们已经见识了x-www-form-urlencoded类型的参数处理,现在越来越多的应用习惯使用JSON来通信,也就是无论返回的response还是提交的request,其content-type类型都是application/json的格式。而对于一些旧的web表单页还是x-www-form-urlencoded的形式,这就需要我们的服务器能支持住这多种content-type的参数了。

由于go是静态语言,需要先实现定义数据模型,这就需要用到gin的model bind功能了。

gin使用go-playground/validator.v8验证参数,查看完整文档。

需要在绑定的字段上设置tag,比如,绑定格式为json,需要这样设置json:"fieldname" 。

此外,Gin还提供了两套绑定方法:

1.Must bind

  • Methods - Bind, BindJSON, BindXML, BindQuery, BindYAML
  • Behavior - 这些方法底层使用 MustBindWith,如果存在绑定错误,请求将被以下指令中止 .

c.AbortWithError(400, err).SetType(ErrorTypeBind),

响应状态代码会被设置为400,请求头Content-Type被设置为text/plain; charset=utf-8。

注意,如果你试图在此之后设置响应代码,将会发出一个警告 [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422,如果你希望更好地控制行为,请使用ShouldBind相关的方法

2.Should bind

  • Methods - ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML
  • Behavior - 这些方法底层使用 ShouldBindWith,如果存在绑定错误,则返回错误,开发人员可以正确处理请求和错误。

当我们使用绑定方法时,Gin会根据Content-Type推断出使用哪种绑定器,如果你确定你绑定的是什么,你可以使用MustBindWith或者BindingWith。

你还可以给字段指定特定规则的修饰符,如果一个字段用binding:"required"修饰,并且在绑定时该字段的值为空,那么将返回一个错误。

type Person struct {
   Name string `json:"name" binding:"required"`      // json格式从name取值,并且该值为必须的
   Age  int    `json:"age" binding:"required,gt=20"` // json格式从age取值,并且该值为必须的,且必须大于20
}

func main() {
   router := gin.Default()
   router.POST("/test", func(context *gin.Context) {
      var person Person
      // 这里我确定传过来的一定是JSON所以用ShouldBindJSON,否则可以用ShouldBind
      if err := context.ShouldBindJSON(&person); err != nil {
         context.JSON(http.StatusBadRequest, gin.H{
            "error": err.Error(),
         })
         return
      }
      context.JSON(http.StatusOK, gin.H{
         "success": true,
      })
   })
   router.Run(":8080")
}
curl http://localhost:8080/test -X POST -d '{"name":"Rock","age": 25}'

上面是通过json映射方式 绑定 请求数据,并且对请求数据进行验证。

自定义参数验证

验证包 gopkg.in/go-playground/validator.v8使用方法

package main

import (
   "net/http"
   "reflect"
   "time"

   "github.com/gin-gonic/gin"
   "github.com/gin-gonic/gin/binding"
   "gopkg.in/go-playground/validator.v8"
)

type Booking struct {
   // 这里的验证方法为bookabledate
   CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
   // gtfield=CheckIn表示大于的字段为CheckIn
   CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
}

func bookableDate(
   v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
   field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
) bool {
   // 这里有两个知识点,映射和断言
   // 在这里,field是一个reflect.Type的接口类型变量,通过Interface方法获得field接口类型变量的真实类型,可以理解为reflect.Value的逆操作
   // 在这里,断言就是将一个接口类型的变量转化为time.Time,前提是后者必须实现了前者的接口
   // 综上,这里就是将field进行了类型转换
   if date, ok := field.Interface().(time.Time); ok {
      today := time.Now()
      if today.Year() > date.Year() || today.YearDay() > date.YearDay() {
         return false
      }
   }
   return true
}

func main() {
   route := gin.Default()

   // 注册自定义验证器
   if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
      v.RegisterValidation("bookabledate", bookableDate)
   }

   route.GET("/bookable", getBookable)
   route.Run(":8080")
}

func getBookable(c *gin.Context) {
   var b Booking
   if err := c.ShouldBindWith(&b, binding.Query); err == nil {
      c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
   } else {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   }
}

上面方法自定义了一种参数验证器。

项目结构参考

├── conf #项目配置文件目录 │ └── config.toml #大家可以选择自己熟悉的配置文件管理工具包例如:toml、xml等等 ├── controllers #控制器目录,按模块存放控制器(或者叫控制器函数),必要的时候可以继续划分子目录。 │ ├── food.go │ └── user.go ├── main.go #项目入口,这里负责Gin框架的初始化,注册路由信息,关联控制器函数等。 ├── models #模型目录,负责项目的数据存储部分,例如各个模块的Mysql表的读写模型。 │ ├── food.go │ └── user.go ├── static #静态资源目录,包括Js,css,jpg等等,可以通过Gin框架配置,直接让用户访问。 │ ├── css │ ├── images │ └── js ├── logs #日志文件目录,主要保存项目运行过程中产生的日志。 └── views #视图模板目录,存放各个模块的视图模板,当然有些项目只有api,是不需要视图部分,可以忽略这个目录 └── index.html

Gin框架运行模式

为方便调试,Gin 框架在运行的时候默认是debug模式,在控制台默认会打印出很多调试日志,上线的时候我们需要关闭debug模式,改为release模式。

设置Gin框架运行模式:

通过环境变量设置 export GIN_MODE=release

GIN_MODE环境变量,可以设置为debug或者release

通过代码设置

在main函数,初始化gin框架的时候执行下面代码
// 设置 release模式
gin.SetMode(gin.ReleaseMode)
// 或者 设置debug模式
gin.SetMode(gin.DebugMode)

Gin如何获取客户ip

route.GET("/ip", func(c *gin.Context) {
   // 获取用户IP
   ip := c.ClientIP()
   c.JSON(http.StatusBadRequest, gin.H{"ip": ip})
})

Gin处理请求结果

以String类型响应请求

func (c *Context) String(code int, format string, values ...interface{})
c.String(200,"欢迎访问%s, 你是%s", "tizi360.com!","最靓的仔!")

以Json格式响应请求

我们开发api接口的时候常用的格式就是json,下面是返回json格式数据的例子

// User 定义
type User struct {
  Name  string `json:"name"` // 通过json标签定义struct字段转换成json字段的名字。
  Email string `json:"email"`
}

// Handler 控制器
func(c *gin.Context) {
  //初始化user对象
  u := &User{
    Name:  "tizi365",
    Email: "tizi@tizi365.com",
  }
  //返回json数据
  //返回结果:{"name":"tizi365", "email":"tizi@tizi365.com"}
  c.JSON(200, u)
}

以文件形式响应请求

  c.FileAttachment("/var/www/1.jpg", "1.jpg")

设置http响应头

func(c *gin.Context) {
  //设置http响应 header, key/value方式,支持设置多个header
  c.Header("site","tizi365")
}

Gin处理html模板

func main() {
    // 初始化gin对象
    router := gin.Default()
    // 首先加载templates目录下面的所有模版文件,模版文件扩展名随意
    router.LoadHTMLGlob("templates/*")
    // 绑定一个url路由 /index
    router.GET("/index", func(c *gin.Context) {
            // 通过HTML函数返回html代码
            // 第二个参数是模版文件名字
            // 第三个参数是map类型,代表模版参数
            // gin.H 是map[string]interface{}类型的别名
            c.HTML(http.StatusOK, "index.html", gin.H{
                    "title": "Main website",
            })
    })
    // 启动http服务,并且绑定在8080端口
    router.Run(":8080")
}

Gin访问静态资源文件

func main() {
    router := gin.Default()
    // 设置静态资源文件目录,并且绑定一个Url前缀
    // 静态资源文件目录:/var/www/tizi365/assets
    // /assets是访问静态资源的url前缀
    // 例如:
    //   /assets/images/1.jpg 这个url文件,存储在/var/www/tizi365/assets/images/1.jpg
    router.Static("/assets", "/var/www/tizi365/assets")

    // 为单个静态资源文件,绑定url
    // 这里的意思就是将/favicon.ico这个url,绑定到./resources/favicon.ico这个文件
    router.StaticFile("/favicon.ico", "./resources/favicon.ico")

    // Listen and serve on 0.0.0.0:8080
    router.Run(":8080")
}

Gin处理Cookie操作

package main

import (
   "fmt"
   "github.com/gin-gonic/gin"
)

func main() {
   router := gin.Default()
   // 设置cookie路由
   router.GET("/setCookie", func(c *gin.Context) {
      // 设置cookie
      c.SetCookie("site_cookie", "cookievalue", 3600, "/", "localhost", false, true)
   })
   // 获得cookie路由
   router.GET("/cookie", func(c *gin.Context) {
      data, err := c.Cookie("/cookie")
      fmt.Printf(data)
      if err != nil {
         // 直接返回cookie值
         c.String(200, data)
         return
      }
      c.String(200, "not found!")
   })
   //删除cookie路由
   router.GET("/removeCookie", func(c *gin.Context) {
      c.SetCookie("set_cookie", "cookievalue", -1, "/", "localhost", false, true)
      c.String(200, "删除cookie")
   })
   router.Run(":8080")
}

Gin文件上传

package main

// 导入gin包
import (
   "fmt"
   "github.com/gin-gonic/gin"
   "log"
   "net/http"
)

func main() {
   router := gin.Default()
   // 设置文件上传大小限制,默认是32m
   router.MaxMultipartMemory = 64 << 20 // 64 MiB

   router.POST("/upload", func(c *gin.Context) {
      // 获取上传文件,返回的是multipart.FileHeader对象,代表一个文件,里面包含了文件名之类的详细信息
      // file是表单字段名字
      file, _ := c.FormFile("file")
      // 打印上传的文件名
      log.Println(file.Filename)

      // 将上传的文件,保存到./data/1111.jpg 文件中
      c.SaveUploadedFile(file, "./data/1111.jpg")

      c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
   })
   router.Run(":8080")
}

Gin中间件

在Gin框架中,中间件(Middleware)指的是可以拦截http请求-响应生命周期的特殊函数,在请求-响应生命周期中可以注册多个中间件,每个中间件执行不同的功能,一个中间执行完再轮到下一个中间件执行。

中间件的常见应用场景如下:

  • 请求限速
  • api接口签名处理
  • 权限校验
  • 统一错误处理

Gin支持设置全局中间件和针对路由分组设置中间件,设置全局中间件意思就是会拦截所有请求,针对分组路由设置中间件,意思就是仅对这个分组下的路由起作用。

 package main

// 导入gin包
import (
   "fmt"
   "github.com/gin-gonic/gin"
   "log"
   "time"
)

// 自定义个日志中间件
func Logger() gin.HandlerFunc {
   return func(c *gin.Context) {
      t := time.Now()

      // 可以通过上下文对象,设置一些依附在上下文对象里面的键/值数据
      c.Set("example", "12345")
      fmt.Printf("1. 执行中间件设置 \n")
      // 在这里处理请求到达控制器函数之前的逻辑

      // 调用下一个中间件,或者控制器处理函数,具体得看注册了多少个中间件。
      c.Next()
      fmt.Printf("4. 完成 执行中间件设置 \n")
      // 在这里可以处理请求返回给用户之前的逻辑
      latency := time.Since(t)
      log.Print(latency)

      // 例如,查询请求状态吗
      status := c.Writer.Status()
      log.Println(status)
   }
}

func main() {
   r := gin.New()
   // 注册上面自定义的日志中间件
   r.Use(Logger())

   r.GET("/test", func(c *gin.Context) {
      // 查询我们之前在日志中间件,注入的键值数据
      fmt.Printf("2. 开始执行业务逻辑 \n")
      example := c.MustGet("example").(string)

      // it would print: "12345"
      log.Println(example)
      fmt.Printf("3. 业务逻辑执行完成 \n")
   })

   // Listen and serve on 0.0.0.0:8080
   r.Run(":8080")
}

其输出结果如下:

1. 执行中间件设置 
2. 开始执行业务逻辑 
2022/10/22 16:33:29 12345
3. 业务逻辑执行完成 
4. 完成 执行中间件设置 
2022/10/22 16:33:29 658.681µs
2022/10/22 16:33:29 200

Gin 中间件类似 Node中的洋葱模型。

以上就是Golang中Gin框架的使用入门教程的详细内容,更多关于Golang Gin框架的资料请关注我们其它相关文章!

(0)

相关推荐

  • golang gin框架实现大文件的流式上传功能

    目录 upload.html gin_stream_upload_file.go 一般来说,通过c.Request.FormFile()获取文件的时候,所有内容都全部读到了内存.如果是个巨大的文件,则可能内存会爆掉:且,有的时候我们需要一边上传一边处理.以下的代码实现了大文件流式上传.还非常不完美,但是可以作为参考: upload.html <!DOCTYPE html> <html lang="en"> <head> <meta charse

  • Golang详细讲解常用Http库及Gin框架的应用

    目录 1. Http标准库 1.1 http客户端 1.2 自定义请求头 1.3 检查请求重定向 1.4 http服务器性能分析 2. JSON数据处理 2.1 实体序列化 2.2 处理字段为小写下划线 2.3 省略空字段 2.4 反序列化 3. 自然语言处理 3.1 使用Map处理 3.2 定义实体处理 4. http框架 4.1 gin 4.1.1 启动服务 4.1.2 middleware 4.1.3 设置请求ID 1. Http标准库 1.1 http客户端 func main() {

  • Golang Gin框架实现文件下载功能的示例代码

    目录 Layui框架实现文件上传 Gin框架获取前端上传的文件 Gin框架的文件下载 Layui框架实现文件上传 基本的思路就是随便创建一个元素,然后使用layui的upload组件对创建的元素进行渲染,详见代码 <!DOCTYPE html> <html lang="en"> <head> <script src="jquery-3.5.0.min.js" type="text/javascript"&

  • golang gin框架获取参数的操作

    1.获取URL参数 GET请求参数通过URL传递 URL参数可以通过DefaultQuery()或Query()方法获取 DefaultQuery()若参数不存在,返回默认值,Query()若参数不存在,返回空串 user_id := com.StrTo(ctx.Query("user_id")).MustInt64() page := com.StrTo(ctx.DefaultQuery("page", "1")).MustInt() 2.获取

  • GO语言gin框架实现管理员认证登陆接口

    后台用户登录验证功能是很多项目的必须要有的逻辑 , 也是常见的技术需求 . 要实现这个逻辑首先要有数据库表结构如下: CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '', `password` varchar(50) NOT NULL DEFAULT '', `nickname` varchar(50) NOT NULL DEFAULT '', `cr

  • Golang中Gin框架的使用入门教程

    目录 安装与简单测试 常见请求与分组请求 获取参数 与 参数合法性验证 获得query中参数 获得multipart/urlencoded form中的参数 模型绑定和参数验证 自定义参数验证 项目结构参考 Gin框架运行模式 Gin如何获取客户ip Gin处理请求结果 以String类型响应请求 以Json格式响应请求 以文件形式响应请求 设置http响应头 Gin处理html模板 Gin访问静态资源文件 Gin处理Cookie操作 Gin文件上传 Gin中间件 官方地址:gin-gonic.

  • golang中gin框架接入jwt使用token验证身份

    目录 jwt 流程: 1.这里使用开源的 jwt-go 1.token 工具类 2. 使用该中间件 3. controller部分代码 jwt jwt的原理和session有点相像,其目的是为了解决rest api中无状态性 因为rest接口,需要权限校验.但是又不能每个请求都把用户名密码传入,因此产生了这个token的方法 流程: 用户访问auth接口,获取token 服务器校验用户传入的用户名密码等信息,确认无误后,产生一个token.这个token其实是类似于map的数据结构(jwt数据结

  • python中的flask框架Jinja 模板入门教程

    目录 1.快速体验 2.Flask 最小 DEMO 3.模板继承 4.Super Blocks 5.Macros 6.自定义过滤器 7.结论 Flask 和 Django 附带了强大的 Jinja 模板语言. 对于之前没有接触过模板语言的人来说,这类语言基本上就是包含一些变量,当准备渲染呈现 HTML 时,它们会被实际的值替换. 这些变量放在标记或分隔符之前.例如:Jinja 模板使用 {% ... %} 表示循环,{{ ... }} 表示一个表达式运算结果返回. Jinja 模板其实是 htm

  • JavaScript的React框架中的JSX语法学习入门教程

    什么是JSX? 在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代码里直接写起了XML标签,实质上这只是一个语法糖,每一个XML标签都会被JSX转换工具转换成纯Javascript代码,当然你想直接使用纯Javascript代码写也是可以的,只是利用JSX,组件的结构和组件之间的关系看上去更加清晰. var MyComponent = React.createClass({/*...*/}); var myElement = <MyComponent som

  • Spring mvc整合tiles框架的简单入门教程(maven)

    前言 本教程基于Springmvc,Spring MVC是当前最优秀的MVC框架,自从Spring 2.5版本发布后,由于支持注解配置,易用性有了大幅度的提高.Spring 3.0更加完善,实现了对Struts 2的超越.现在越来越多的开发团队选择了Spring MVC. Tiles 框架彻底揭示了 jsp:includes 内部的概念 ―― 从而允许您更灵活地创建可重用的页面.使用 Tiles 框架,开发人员能够通过组合可重用的 tile 来构建页面.您应该将 tile 看作是可视组件. 下面

  • Django框架模板用法入门教程

    本文实例讲述了Django框架模板用法.分享给大家供大家参考,具体如下: Django 模板标签 if/else 标签 基本语法格式如下: {% if condition %} ... display {% endif %} 或者: {% if condition1 %} ... display 1 {% elif condition2 %} ... display 2 {% else %} ... display 3 {% endif %} 根据条件判断是否输出.if/else 支持嵌套. {

  • 高性能PHP框架Symfony2经典入门教程

    Symfony2是一个基于PHP语言的Web开发框架,有着开发速度快.性能高等特点.本文以一个程序示例的实现过程详细叙述了Symfony2框架的配置与程序开发. 一.下载 首先是下载Symfony2,到 http://symfony.com/download或者本站下载http://www.jb51.net/codes/187833.html.本人以Ubuntu系统为例,采用.tgz的压缩包,解压源文件到/var/www目录中并执行: tar zxvf Symfony_Standard_Vend

  • Django 框架模型操作入门教程

    本文实例讲述了Django 框架模型操作.分享给大家供大家参考,具体如下: Django 对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite.Oracle. Django 为这些数据库提供了统一的调用API. 我们可以根据自己业务需求选择不同的数据库. MySQL 是 Web 应用中最常用的数据库.本章以mysql为例. 如果没安装 mysql 驱动,可以执行以下命令安装: sudo pip3 install mysqlclient 数据库配置 在项目的 sett

  • Android应用开发中Action bar编写的入门教程

    从Android 3.0开始除了我们重点讲解的Fragment外,Action Bar也是一个重要的内容,Action Bar主要是用于代替传统的标题栏,对于Android平板设备来说屏幕更大它的标题使用Action Bar来设计可以展示更多丰富的内容,方便操控. Action Bar主要功能包含: 1. 显示选项菜单 2. 提供标签页的切换方式的导航功能,可以切换多个fragment. 3. 提供下拉的导航条目. 4. 提供交互式活动视图代替选项条目 5. 使用程序的图标作为返回Home主屏或

  • 分分钟学会vue中vuex的应用(入门教程)

    vuex.js 状态(数据)管理 在vue中当我们管理数据的时候比较乱,我们要用到下面的这个库,vuex.js Vuex介绍 每一个Vuex应用的核心就是store(仓库),他是用来存储数据的 "store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state).Vuex 和单纯的全局对象有以下两点不同 1.Vuex 的状态存储是响应式的 2.你不能直接改变 store 中的状态 vuex有6个概念 Store(最基本的概念)(创库) State (数据) Getters(

随机推荐