使用Gin快速开发基于Go语言的Web系统

快速入门

  1. 安装并配置GO工作区
  2. 在GOPATH的src目录下新建项目文件夹
  3. 使用 go mod init命令初始化项目
  4. 使用go get -u github.com/gin-gonic/gin命令安装gin
  5. 示例代码:
package main

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

func main() {
    // 创建默认路由
 r := gin.Default()
    // 绑定路由规则和执行函数,当访问/ping接口时就会执行后面的函数
 r.GET("/ping"func(c *gin.Context) {
        // 该函数直接返回JSON字符串
  c.JSON(200, gin.H{
   "message""pong",
  })
 })
    // 启动并监听端口,默认8080,可使用:r.Run(":8000")修改监听端口
 r.Run()
}
  1. 浏览器或postman访问:localhost:8080/ping,即可成功返回json字符串

路由

API参数

在路径中使用/:paramName或者/*paramName作为占位符,可在代码中通过*gin.Contextparam方法获取到API参数,使用冒号占位符获取到的API参数不包含路径中的/,使用星号占位符则包含/

func main() {
    // 创建路由
    r := gin.Default()   
 r.GET("/user/:name/*action"func(c *gin.Context) {
        name := c.Param("name")
        action := c.Param("action")
        c.JSON(http.StatusOK, gin.H{
            "name":name,
            "action":action,
        })
    })
    // 默认端口号是8080
 r.Run(":8000")
}

使用postman请求http://127.0.0.1:8000/user/lee/index.html,返回的json格式如下:

{
    "action""/index.html",
    "name""lee"
}

URL参数

使用DefaultQuery或者Query方法可以获取前端传递的URL参数

DefaultQuery:可指定默认值

Query:不可指定默认值

func main() {
    // 创建路由
    r := gin.Default()
    r.GET("/add_user"func(c *gin.Context) {
        name := c.Query("name")
        age := c.DefaultQuery("age""23")
        c.JSON(http.StatusOK, gin.H{
            "name":name,
            "age":age,
        })
    })
    // 默认端口号是8080
 r.Run(":8000")
}

postman访问:http://127.0.0.1:8000/add_user?name=lee&age=18,返回如下:

{
    "age""18",
    "name""lee"
}

postma访问:http://127.0.0.1:8000/add_user?name=lee,返回如下:

{
    "age""23",
    "name""lee"
}

表单参数

  • 表单传输为post请求,http常见的传输格式为四种:

    • application/json

    • application/x-www-form-urlencoded

    • application/xml

    • multipart/form-data

表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencoded或from-data格式的参数,还可以使用DefaultPostForm方法指定默认值获取。

func main() {
    // 创建路由
    r := gin.Default()
 r.POST("/form_post"func(c *gin.Context) {
        message := c.DefaultPostForm("message""default message")
        name := c.PostForm("name")
        c.JSON(http.StatusOK, gin.H{
            "message":message,
            "name":name,
        })
    })
    // 默认端口号是8080
 r.Run(":8000")
}

使用postman发送请求如下所示:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

上传单个文件

func main() {
    // 创建路由
    r := gin.Default()
    r.POST("/upload"func(c *gin.Context) {
        file, err := c.FormFile("file")
        if err != nil {
            fmt.Println(err)
        }
        c.SaveUploadedFile(file, file.Filename)
        c.JSON(http.StatusOK, gin.H{
            "message":"ok",
            "fileName":file.Filename,
        })
    })
    // 默认端口号是8080
 r.Run(":8000")
}

使用postman发送请求如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

上传特定文件

func main() {
    // 创建路由
    r := gin.Default()
    r.POST("/upload"func(c *gin.Context) {
        _, file, err := c.Request.FormFile("file")
        if err != nil {
            fmt.Println(err)
        }
        if file.Size >= 1024 * 1024 * 2 {
            c.JSON(http.StatusOK, gin.H{
                "message":"文件大小不能超过2M",
            })
            return
        }
        if file.Header.Get("Content-Type") != "image/png" {
            c.JSON(http.StatusOK, gin.H{
                "message":"只能上传png格式文件",
            })
            return
        }
        c.SaveUploadedFile(file, file.Filename)
        c.JSON(http.StatusOK, gin.H{
            "message":"ok",
            "fileName":file.Filename,
        })
    })
 // 默认端口号是8080
 r.Run(":8000")
}

使用postman发送请求如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

上传多个文件

func main() {
    // 创建路由
    r := gin.Default()
 r.POST("/upload"func(c *gin.Context) {
  form, err := c.MultipartForm()
  if err != nil {
   fmt.Println(err)
   return
  }
  files := form.File["files"]
  for _, file := range files {
   err := c.SaveUploadedFile(file, file.Filename)
   if err != nil {
    c.JSON(http.StatusOK, gin.H{
     "message":"文件上传失败",
     "err":err,
    })
    return
   }
  }
  c.JSON(http.StatusOK, gin.H{
   "message":"文件上传成功",
   "upload file count":len(files),
  })
 })
    // 默认端口号是8080
 r.Run(":8000")
}

使用postman调用接口如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

路由组

路由组(RouterGroup),用于管理一组路由,在不同路由组中的路由可重名

func main() {
    // 创建路由
    r := gin.Default()
 v1 := r.Group("/v1")
 v1.GET("/hello"func(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
   "message":"/v1/hello",
  })
 })

 v2 := r.Group("/v2")
 v2.GET("/hello"func(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
   "message":"/v2/hello",
  })
 })
    // 默认端口号是8080
 r.Run(":8000")
}

postman分别访问http://127.0.0.1:8000/v1/hellohttp://127.0.0.1:8000/v2/hello,返回不同的消息

自定义404

定义NoRoute之后,如果访问的地址不在已经存在的路由中,就会默认执行这个配置的方法,可用于配置404返回信息

func main() {
    // 创建路由
    r := gin.Default()
 r.NoRoute(func(c *gin.Context) {
  c.JSON(http.StatusNotFound, gin.H{
   "message":"页面丢了!",
  })
 })
    // 默认端口号是8080
 r.Run(":8000")
}

使用postman调用结果如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

数据绑定

JSON

将前端发送的json数据绑定到结构体上,在结构体中除了定义结构体的参数之外,在参数后面需要定义json的参数名,表示将json中的哪个参数与结构体中的参数进行绑定,binding:"required"表示该字段为必传,如果为空则报错

func main() {
    // 创建路由
    r := gin.Default()
 r.GET("/loginJSON"func(c *gin.Context) {
  var login LoginForm
  err := c.ShouldBindJSON(&login)
  if err != nil {
   c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   return
  }
  // 判断用户名密码是否正确
  if login.User != "root" || login.Password != "admin" {
   c.JSON(http.StatusBadRequest, gin.H{
    "status""304",
    "message":"登录失败",
   })
   return
  }
  c.JSON(http.StatusOK, gin.H{
   "status""200",
   "message":"登录成功",
  })
 })
    // 默认端口号是8080
 r.Run(":8000")
}


type LoginForm struct {
    // 表明该属性与传递的json的user属性进行绑定
 User     string `json:"user" binding:"required"`
 Password string `json:"password" binding:"required"`
}

使用postman调用接口结果如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

表单

func main() {
    // 创建路由
    r := gin.Default()
 r.POST("/loginForm"func(c *gin.Context) {
  // 声明接收的变量
  var form LoginForm
  // Bind()默认解析并绑定form格式
  // 根据请求头中content-type自动推断
  if err := c.Bind(&form); err != nil {
   c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   return
  }
  if form.User != "root" || form.Password != "admin" {
   c.JSON(http.StatusBadRequest, gin.H{
    "status""304",
    "message":"登录失败",
   })
   return
  }
  c.JSON(http.StatusOK, gin.H{
   "status""200",
   "message":"登录成功",
  })
 })
 // 默认端口号是8080
 r.Run(":8000")
}

type LoginForm struct {
 User     string `form:"user" json:"user" binding:"required"`
 Password string `form:"password" json:"password" binding:"required"`
}

使用postman调用接口结果如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

URI

func main() {
    // 创建路由
    r := gin.Default()
 r.GET("/login/:user/:password"func(c *gin.Context) {
  // 声明接收的变量
  var login LoginForm
  // Bind()默认解析并绑定form格式
  // 根据请求头中content-type自动推断
  if err := c.ShouldBindUri(&login); err != nil {
   c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
   return
  }
  if login.User != "root" || login.Password != "admin" {
   c.JSON(http.StatusBadRequest, gin.H{
    "status""304",
    "message":"登录失败",
   })
   return
  }
  c.JSON(http.StatusOK, gin.H{
   "status""200",
   "message":"登录成功",
  })
 })
 // 默认端口号是8080
 r.Run(":8000")
}

type LoginForm struct {
 User     string `form:"user" json:"user" uri:"user" binding:"required"`
 Password string `form:"password" json:"password" uri:"password" binding:"required"`
}

使用postman调用结果如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

数据响应

JSON、Struct、XML、YAML

func main() {
    // 创建路由
    r := gin.Default()
 // JSON响应
 r.GET("/someJSON"func(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
   "message":"JSON OK",
  })
 })

 // 结构体响应
 r.GET("/someStruct"func(c *gin.Context) {
  type Msg struct {
   Message string
  }
  msg := Msg{
   Message: "Struct OK",
  }
  c.JSON(http.StatusOK, msg)
 })

 // XML响应
 r.GET("/someXML"func(c *gin.Context) {
  c.XML(http.StatusOK, gin.H{
   "message":"XML OK",
  })
 })

 // YAML响应
 r.GET("/someYAML"func(c *gin.Context) {
  c.YAML(http.StatusOK, gin.H{
   "message":"YAML OK",
  })
 })
    // 默认端口号是8080
 r.Run(":8000")
}

不同响应方式返回示例:

// JSON返回
{
    "message""JSON OK"
}
// Struct返回
{
    "Message""Struct OK"
}
<!-- XML返回 -->
<map>
    <message>XML OK</message>
</map>
# YAML返回
message: YAML OK

重定向

func main() {
    // 创建路由
    r := gin.Default()
 r.GET("/redirect"func(c *gin.Context) {
  c.Redirect(http.StatusMovedPermanently, "https://www.baidu.com")
 })
 // 默认端口号是8080
 r.Run(":8000")
}

重定向之后当使用浏览器访问http://127.0.0.1:8000/redirect链接则会自动跳转到百度首页

同步异步

func main() {
    // 创建路由
    r := gin.Default()
 r.GET("/async"func(c *gin.Context) {
  copyContext := c.Copy()
  go func() {
   time.Sleep(time.Second * 3)
   log.Println("异步执行:" + copyContext.Request.URL.Path)
  }()
  c.JSON(http.StatusOK, gin.H{
   "message":"OK",
  })
 })

 r.GET("/sync"func(c *gin.Context) {
  time.Sleep(3 * time.Second)
  log.Println("同步执行:" + c.Request.URL.Path)
        c.JSON(http.StatusOK, gin.H{
   "message":"OK",
  })
 })
    // 默认端口号是8080
 r.Run(":8000")
}

在异步中,访问接口,会直接返回message:OK响应,然后后台在3秒之后打印异步执行提示消息

在同步中,访问接口,需要等待3秒之后才会打印并响应

中间件

全局中间件

定义全局中间件之后,所有的请求都会经过该中间件

func main() {
    // 创建路由
    r := gin.Default()
 // 注册中间件
 r.Use(MiddleWare())
    // 大括号只是为了代码规范,没有大括号也不会有问题
 {
  r.GET("/middle"func(c *gin.Context) {
   fmt.Println("接口执行了..")
   value, _ := c.Get("middleParam")
   c.JSON(http.StatusOK, gin.H{
    "middleParam":value,
   })
  })
 }
 // 默认端口号是8080
 r.Run(":8000")
}

// 定义中间件
func MiddleWare() gin.HandlerFunc {
 return func(c *gin.Context) {
  start := time.Now()
  fmt.Println("中间件执行了..")
  // 将变量到Context中,可以通过Get(key)取
  c.Set("middleParam""middle")
  // 执行函数
  c.Next()
  // 中间件执行完后续操作
  duration := time.Since(start)
  fmt.Println("执行中间件耗时:", duration)
 }
}

在代码中定义了一个中间件,并在中间件中放入了middleParam参数,然后在接口中可以将该参数取出,并且中间件总是会在接口执行之前执行。

使用postman调用接口如下:

使用Gin快速开发基于Go语言的Web系统
postman发送请求

日志输出如下:

使用Gin快速开发基于Go语言的Web系统
日志

局部中间件

局部中间件仅在当前接口有用。

func main() {
    // 创建路由
    r := gin.Default()
 r.GET("/middle_local", MiddleWare(), func(c *gin.Context) {
  value, _ := c.Get("middleParam")
  c.JSON(http.StatusOK, gin.H{
   "middleParam":value,
  })
 })
 // 默认端口号是8080
 r.Run(":8000")
}

Cookie

Cookie介绍

  • HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出,Cookie就是解决HTTP协议无状态的方案之一

  • Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求。

  • Cookie由服务器创建,并发送给浏览器,最终由浏览器保存。

Cookie使用

func main() {
    // 创建路由
    r := gin.Default()
 r.GET("/cookie"func(c *gin.Context) {
        // 获取客户端是否携带cookie
       cookie, err := c.Cookie("cookie_key")
        if err != nil {
            cookie = "NotSet"
            // 给客户端设置cookie
            // maxAge:有效期,单位为秒
            // path:cookie所在目录
            // domain:域名
            // secure:是否只能通过https访问
            // httpOnly:是否允许别人通过js获取自己的cookie
            c.SetCookie("cookie_key""cookie_value"60"/""localhost"falsetrue)
        }
        fmt.Printf("cookie的值是: %sn", cookie)
 })
 // 默认端口号是8080
 r.Run(":8000")
}

参数校验

Struct结构体校验

type Person struct {
    // name必填
 Name string `form:"name" binding:"required"`
    // age必填并且大于10
 Age int `form:"age" binding:"required,gt=10"`
    // birthday格式化"2006-01-02"
 Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
}

func main() {
    // 创建路由
    r := gin.Default()
 r.GET("/struct_verify"func(c *gin.Context) {
  var person Person
  err := c.ShouldBind(&person)
  if err != nil {
   fmt.Println("Error:", err)
   c.String(http.StatusBadRequest, fmt.Sprint(err))
   return
  }
  c.String(http.StatusOK, fmt.Sprint(person))
 })
 // 3.监听端口,默认在8080
 // Run("里面不指定端口号默认为8080")
 r.Run(":8000")
}

当name不传,age小于10时返回结果如下:

Key: 'Person.Name' Error:Field validation for 'Name' failed on the 'required' tag
Key: 'Person.Age' Error:Field validation for 'Age' failed on the 'gt' tag

日志

func main() {
 // 禁用颜色显示
 gin.DisableConsoleColor()

 // 新建日志文件
 f, _ := os.Create("gin.log")
 // 将日志写入到文件中
 //gin.DefaultWriter = io.MultiWriter(f)

 // 同时将日志写入文件和控制台
 gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
    // Run("里面不指定端口号默认为8080")
 r.Run(":8000")
}
使用Gin快速开发基于Go语言的Web系统


原文始发于微信公众号(良猿):使用Gin快速开发基于Go语言的Web系统

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/215932.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!