GoWeb——Gin框架的使用

1、 Gin框架简介

Gin是一个用Go语言编写的Web框架。Gin框架拥有很好的性能,其借助高性能的HttpRouter包,运行速度得到了极大提升。目前的Gin框架是1.x版本。

2、Gin框架安装与第一个Gin示例

2.1、安装

下载并安装Gin:

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

2.2、第一个Gin示例

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

func main() {
	//创建一个默认的路由引擎
	r := gin.Default()
	//GET:请求方式;/hello:请求的路径
	//当客户端以GET方法请求/hello路径时,会执行后面的匿名函数
	r.GET("/hello", func(c *gin.Context) {
		//c.JSON:返回JSON格式的数据
		c.JSON(200, gin.H{
			"messages": "Hello world!",
		})
	})
	//启动HTTP服务,默认在0.0.0.0:8080启动服务
	r.Run()
}

运行以上代码,然后使用浏览器打开“127.0.0.1:8080/hello”即可看到一串JS0N字符串。

3、Gin路由和控制器

路由是指:一个HTTP请求找到对应的处理器函数的过程。处理器函数主要负责执行HTTP请求和响应任务。如下代码中的goLogin(0函数就是Gin的处理器函数:

r := gin.Default()
r.POST("/usr/login", goLogin)

//处理器函数
func goLogin(c *gin.Context) {
	name := c.PostForm("name")
	password := c.POstForm("password")
	//通过请求上下文对象Context,直接给客户端返回一个字符串
	c.String(200, "username=%s,password=%s", name, password)
}

3.1、路由规则

一条路由规则由HTTP请求方法、URL路径、处理器函数这3部分组成。

3.1.1、HTTP请求方法

常用的HTTP请求方法有GET、POST、PUT、DELETE这4种。

3.1.2、URL路径

Gin框架的URL路径有以下3种写法。

1.静态URL路径,即不带任何参数的URL路径。形如:

/users/shirdon
/user/1
/article/6

2.带路径参数的URL路径,URL路径中带有参数,参数由英文冒号“:”跟着1个字符串定义。形如:

定义参数:id

以上形式可以匹配user/1、/article/6这类的URL路径。

3.带星号(*)模糊匹配参数的URL路径

星号(*)代表匹配任意路径的意思。必须在*号后面指定一个参数名,之后可以通过这个参数获取*号匹配的内容。例如“/user/*path”可以通过path参数获取*号匹配的内容,例如/user/1user/shirdon/comment/1等。

3.1.3、处理器函数

Gin框架的处理器函数的定义如下:

func HandlerFunc(c *gin.Context)

处理器函数接受1个上下文参数。可以通过上下文参数获取HTTP的请求参数,返回HTTP请求的响应。

3.2、分组路由

在做API开发时,如果要支持多个API版本,则可以通过分组路由来处理API版本。Gi的分组路由示例如下:

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

func main() {
	router := gin.Default()
	//创建v1组
	v1 := router.Group("/v1")
	{
		v1.GET("/login", login1)
	}
	//创建v2组
	v2 := router.Group("v2")
	{
		v2.GET("/login", login2)
	}
	router.Run()
}

func login1(c *gin.Context) {
	c.JSON(200, gin.H{
		"message": "hello1",
	})
}

func login2(c *gin.Context) {
	c.JSON(200, gin.H{
		"message": "hello2",
	})
}

上面的例子将会注册下面的路由信息:

/v1/login
/v2/login

4、Gin处理请求参数

4.1、获取GET请求参数

Gin获取GET请求参数的常用方法如下:

func (c *Context)Query(key string)string
func (c *Context)DefaultQuery(key,defaultvalue string)string
func (c *Context)GetQuery(key string)(string,bool)

4.2、获取POST请求参数

Gin获取POST请求参数的常用方法如下:

func (c *Context)PostForm(key string)string
func (c.*Context)DefaultPostForm(key,defaultValue string)string
func (c *Context)GetPostForm(key string)(string,bool)

其使用方法示例如下:

func Handler(c *gin.Context){
	//获取name参数,通过PostForm获取的参数值是String类型
	name := c.PostForm("name")
	//跟PostForm的区别是:可以通过第二个参数设置参数默认值
	name := c.DefaultPostForm("name", "shirdon")
	
	//获取id参数,通过GetPostForm获取的参数值也是String类型
	id, ok := c.GetPostForm("id")
	if !ok {
		//。。。参数不存在
	}
}

4.3、获取URL路径参数

Gin获取URL路径参数是指,获取user:id这类路由绑定的参数。user:id绑定了1个参数id。获取URL路径参数的函数如下:

func (c *Context)Param(key string)string

其使用示例如下:

r := gin.Default()
r.GET("/user/:id",func(c.*gin.Context){
	//获取URL参数id
	id:=c.Param("id")
})

4.4、请求参数绑定到结构体

前面获取参数的方式都是逐个进行参数的读取,比较麻烦。G支持将请求参数自动绑定到一个结构体对象,这种方式支持GET/POST请求,也支持HTTP请求体中内容为JSON或XML格式的参数。下面例子是将请求参数绑定到User结构体:

type User struct {
	Phone string `json:"phone" form:"phone"`
	Age string `json:"age" form:"age"`
}

在上面代码中,通过定义结构体字段的标签,来定义请求参数和结构体字段的关系。下面对User结构体的Phone字段的标签进行说明:

标签说明
json:“phone”数据为JSON格式,并且json字段名为phone
form:“phone”表单参数名为phone

在实际开发中,可以根据自己的需要选择支持的数据类型。下面看一下控制器代码如何使用User结构体:

r.POST("/user/:id", func(c *gin.Context) {
	u := User{}
	if c.ShouldBind(&u) != nil {
		log.Println("bind params fail...")
	}
	c.JSON(200, u)
})

在这里插入图片描述

5、Gin生成HTTP请求响应

接下来探究一下如何在Gin中生成HTTP请求响应。Gin支持以字符串、JSON、XML、文件等格式生成HTTP请求响应。gin.Context上下文对象支持多种返回处理结果。下面分别介绍不同的响应方式。

5.1、以字符串方式生成HTTP请求响应

通过String()方法生成字符串方式的HTTP请求响应。
String()方法的定义如下:

func (c *Context)String(code int,format string,values...interface(})

该方法的使用示例如下:

func stringResponse(c *gin.Context) {
	c.String(200, "hello")
	c.String(200, "hello %s, good %s", "tom", "job")
}

在这里插入图片描述

5.2、以JSON格式生成HTTP请求响应

type User struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

func jsonResponse(c *gin.Context) {
	u := &User{
		Name:  "Shirdon",
		Email: "2342342@qq.com",
	}
	c.JSON(200, u)
}

在这里插入图片描述

5.3、以XML格式生成HTTP请求响应

定义一个User结构体,默认结构体的名字就是XML的根节点名字。以XML格式生成HTTP请求响应的示例如下:

type XmlUser struct {
	Name  string `xml:"name"`
	Email string `xml:"email"`
}

func xmlResponse(c *gin.Context) {
	u := &XmlUser{
		Name:  "Shirdon",
		Email: "234235@qq.com",
	}
	c.XML(200, u)
}

在这里插入图片描述

5.4、以文件格式生成HTTP请求响应

接下来介绍Gin如何直接返回一个文件,这可以用来做文件下载。通过File()方法直接返回本地文件,参数为本地文件地址。其示例如下:

func fileResponse(c *gin.Context) {
	//通过File()方法直接返回本地文件,参数为本地文件地址
	c.File("./a.txt")
}

在这里插入图片描述

5.5、设置HTTP响应头

Gin中提供了Header()方法来设置HTTP响应头。默认采用key/value方式,支持设置多个Header。其使用示例如下:

func headerResponse(c *gin.Context) {
	c.Header("Content-Type", "text/html;charset=utf-8")
	c.Header("site", "tom")
}

在这里插入图片描述

6、渲染HTML模板

6.1、使用 LoadHTMLGlob () 或者 LoadHTMLFiles ()

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("./src/bookWebPro/chapter8/gin/templates/*")
	//router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
	router.GET("/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"title": "Main website",
		})
	})
	router.Run(":8080")
}

index.tmpl

<html>
<h1>
    {{ .title }}
</h1>
</html>

在这里插入图片描述

6.2、使用不同目录下名称相同的模板

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("./src/bookWebPro/chapter8/gin/templates/**/*")
	router.GET("/posts/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
			"title": "Posts",
		})
	})
	router.GET("/users/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
			"title": "Users",
		})
	})
	router.Run(":8080")
}

templates/posts/index.tmpl:

{{ define "posts/index.tmpl" }}
<html><h1>
    {{ .title }}
</h1>
<p>Using posts/index.tmpl</p>
</html>
{{ end }}

templates/users/index.tmpl

<html>
<h1>
    {{ .title }}
</h1>
</html>

在这里插入图片描述

在这里插入图片描述

6.3、自定义模板渲染器

import "html/template"

func main() {
    router := gin.Default()
    html := template.Must(template.ParseFiles("file1", "file2"))
    router.SetHTMLTemplate(html)
    router.Run(":8080")
}

6.4、自定义分隔符

r := gin.Default()
r.Delims("{[{", "}]}")
r.LoadHTMLGlob("/path/to/templates")

6.5、自定义模板功能

import (
    "fmt"
    "html/template"
    "net/http"
    "time"

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

func formatAsDate(t time.Time) string {
    year, month, day := t.Date()
    return fmt.Sprintf("%d/%02d/%02d", year, month, day)
}

func main() {
    router := gin.Default()
    router.Delims("{[{", "}]}")
    router.SetFuncMap(template.FuncMap{
        "formatAsDate": formatAsDate,
    })
    router.LoadHTMLFiles("./testdata/template/raw.tmpl")

    router.GET("/raw", func(c *gin.Context) {
        c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{
            "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
        })
    })

    router.Run(":8080")
}

raw.tmpl

Date: {[{.now | formatAsDate}]}

结果:

Date: 2017/07/01

7、处理静态文件

在Gin中,如果项目中包含JS、CSS、JPG之类的静态文件,可以通过Static()方法配置路径映射:

func main() {
	r := gin.Default()
	r.Static("/assets", "./")
	r.StaticFile("/facicon.ico", "./static/facivon.ico")
	r.Run(":8080")
}

在这里插入图片描述

8、处理cookie

在Go语言net/http包中内置了cookie处理机制。Gin主要通过上下文对象提供的SetCookie()和Cookie()两个方法操作cookie,这两个函数都是对Go语言net/http包中http.SetCookie()方法的重新封装而已,其实质是一样的。

8.1、设置cookie

Gin使用SetCookie()方法设置cookie。SetCookie()方法的定义如下:

func (c *Context).SetCookie(name,value string,maxAge int, path, domain string, secure, httponly bool)

SetCookie()方法的使用示例如下:

func main() {
	r := gin.Default()
	r.GET("/hello", setCookie)
	r.Run(":8080")
}

func setCookie(c *gin.Context) {
	c.SetCookie("my_cookie", "cookievalue", 3600, "/", "localhost", false, true)
}

在这里插入图片描述

8.2、读取Cookie

func main() {
	r := gin.Default()
	r.GET("/hello", getCookie)
	r.Run(":8080")
}

func getCookie(c *gin.Context) {
	//根据cookie名字读取cookie值
	data, err := c.Cookie("my_cookie")
	if err != nil {
		c.String(200, data)
	}
	c.String(200, "not found!")
}

8.3、删除cookie

通过将SetCookie()方法的MaxAge参数设置为-1,以达到删除cookie的目的。示例如下:

func delCookie(c *gin.Context) {
	//设置cookie,将MaxAge设置为-1标识删除cookie
	c.SetCookie("my_cookie", "cookievalue", -1, "/", "localhost", false, true)
}

9、文件上传

Gin使用SaveUploadedFile()方法实现文件上传。其使用示例代码如下。

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

func main() {
	router := gin.Default()
	//设置文件上传大小限制,默认是32MB
	router.MaxMultipartMemory = 64 << 20 //64mb
	router.StaticFile("/upload.html", "./src/bookWebPro/chapter8/gin/templates/upload.html")

	router.POST("/upload", func(c *gin.Context) {
		//file是表单字段名字
		file, _ := c.FormFile("file")
		//打印上传的文件名
		log.Println(file.Filename)
		//将上传的文件保存到./data/shirdon.jpg
		c.SaveUploadedFile(file, "./data/shirdon.jpg")
		c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
	})
	router.Run(":8080")
}

upload.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Gin文件上传</title>
</head>
<body>
    <h1>上传文件示例</h1>
    <form action="http://127.0.0.1:8080/upload" method="post" enctype="multipart/form-data">
        文件:
        <input type="file" name="file"><br><br>
        <input type="submit" value="上传">
    </form>
</body>
</html>

10、中间件

在Gin中,中间件(Middleware)是指可以拦截HTTP请求-响应生命周期的特殊函数。在请求-响应生命周期中可以注册多个中间件。每个中间件执行不同的功能,一个中间件执行完,才轮到下一个中间件执行。中间件的常见应用场景如下:

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

如果想拦截所有请求,则可以开发一个中间件函数来实现。Gin支持设置全局中间件和针对路由分组的中间件。在设置全局中间件后,会拦截所有请求。通过分组路由设置的中间件,仅对这个分组下的路由起作用。

10.1、使用中间件

func main() {
	r := gin.Default()
	//通过Use()方法设置全局中间件
	//设置日志中间件,主要用于打印请求日志
	r.Use(gin.Logger())
	//设置Recovery中间件,主要用于拦截panic错误,不知与宕机
	r.Use(gin.Recovery())
	r.Run()
}

10.2、自定义中间件

import (
	"github.com/gin-gonic/gin"
	"log"
	"time"
)

func main() {
	r := gin.Default()
	//注册中间件
	r.Use(Logger())
	r.GET("/hi", func(c *gin.Context) {
		//在查询之前在日志中间件中注入的键值数据
		example := c.MustGet("example").(string)
		//打印
		log.Println(example)
	})
	r.Run(":8080")
}

//自定义一个日志中间件
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()
		//可以通过上下文对象,设置一些依附在上下文对象里面的键/值数据
		c.Set("example", "hello")
		//在这里处理请求到达处理器函数之前的逻辑

		//调用下一个中间件,或者处理器的处理函数,具体需要看注册了多少个中间件
		c.Next()

		//在这里嗯可以处理返回给客户但之前的响应罗i几
		latency := time.Since(t)
		log.Print(latency)
		//例如,查询请求状态码
		status := c.Writer.Status()
		log.Println(status)
	}
}

11、Gin处理Session

在Gin中,可以依赖“github.com/gin-contrib/sessions”包中的中间件处理session。“github.com/gin-contrib/sessions”包中的中间件支持cookie、MemStore、Redis、Memcached、MongoDB等存储引擎。
下面介绍session的常见用法。

11.1、基于Cookie存储引擎

  1. 安装“github.com/gin-contrib/sessions”包:
go get github.com/gin-contrib/sessions

2、“github.com/gin-contrib/sessions”包中session的用法:

import "github.com/gin-gonic/gin"               //gin框架
import "github.com/gin-contrib/sessions/cookie" //session存储引擎
import "github.com/gin-contrib/sessions"        //session

func main() {
	r := gin.Default()
	//创建基于cookie的存储引擎,password123456参数是用于加密的密钥
	store := cookie.NewStore([]byte("password123456"))
	//这只session中间件,参数my_session指的是session的名字,也是cookie的名字
	//store是前面创建的存储引擎,可以将其替换成其他存储引擎
	r.Use(sessions.Sessions("my_session", store))

	r.GET("/hello", func(c *gin.Context) {
		//初始化session对象
		session := sessions.Default(c)

		//通过session.Get()函数读取session值
		//session是键值对格式数据,因此需要通过key查询数据
		if session.Get("hello") != "world" {
			//设置session数据
			session.Set("hello", "world")
			//删除session数据
			session.Delete("shirdon")
			//保存session数据
			session.Save()
			//删除整个session
			//session.Clear()
		}
		c.JSON(200, gin.H{
			"hello": session.Get("hello"),
		})
	})
	r.Run(":8080")
}

在这里插入图片描述

11.2、基于Redis存储引擎

  1. 安装Giin的Redis存储引擎包
go get github.com/gin-contrib/sessions/redis

2.基于Redis存储引擎的示例

import "github.com/gin-gonic/gin"              //gin框架
import "github.com/gin-contrib/sessions/redis" //redis存储引擎
import "github.com/gin-contrib/sessions"       //session

func main() {
	r := gin.Default()
	//初始化基于Redis的存储引擎
	store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("123456"))
	r.Use(sessions.Sessions("mysession", store))

	r.GET("/incr", func(c *gin.Context) {
		session := sessions.Default(c)
		var count int
		v := session.Get("count")
		if v == nil {
			count = 0
		} else {
			count = v.(int)
			count++
		}
		session.Set("count", count)
		session.Save()
		c.JSON(200, gin.H{"count": count})
	})
	r.Run(":8080")
}

在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值