一、Gin框架介绍

1.1 简介

A. 基于httprouter开发的web框架。 http://github.com/julienschmidt/httprouter

B. 提供Martini风格的API,但比Martini要快40倍

C. 非常轻量级,使用起来非常简洁

1.2 Gin框架的安装与使用

A. 安装: go get -u github.com/gin-gonic/gin

B. import "go get -u github.com/gin-gonic/gin"

实例1:

package main

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

func main() {
r := gin.Default() //Default返回一个默认的路由引擎
r.GET("/ping", func(c *gin.Context) { //c这里就是封装了go底层web的r和w
c.JSON(, gin.H{ //200是状态码
"message": "pong",
}) //输出json结果给调用方
})
r.Run() // listen and serve on 0.0.0.0:8080
}

执行结果:

浏览器查看:

实例2:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) type Result struct {
Message string `json:"message"`
Code int `json:"code"`
} func handleUserInfo(c *gin.Context) { var result Result = Result{ //初始化1个map
Message: "success",
Code: ,
} c.JSON(http.StatusOK, result) //第二个参数是一个空接口,可以传递任何类型数据进来,这里传递进来的map会自动把我们转成json串
} func main() {
r := gin.Default()
r.GET("/user/info", handleUserInfo) r.Run(":9090")
}

执行结果:

浏览器查看:

1.3 Restful风格的API

A. 把我们设计的API抽象成一个个资源,用URI来标识。

B. 针对每一个资源,使用统一的方法进行操作。

C. 同一的方法有:

a. GET,获取资源内容。

b. POST,创建资源。

c. PUT,更新资源。

d. DELETE,删除资源。

样例:

package main

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

func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.POST("/ping", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}

1.4 实例1  restful风格的API 用户信息接口设计,资源就是 /user/info

样例:

package main

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

func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/user/info", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.POST("/user/info", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.PUT("/user/info", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.DELETE("/user/info", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}

1.5 实例2   用户信息接口设计,非restful风格的API

样例:

package main

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

func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/user/info", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.POST("/user/create", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.POST("/user/delete", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.POST("/user/update", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}

二、Gin框架参数传递

2.1 通过querystring传递, 比如: /user/search?username=少林&address=北京

实例1:

package main

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

func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/user/search", func(c *gin.Context) {
//username := c.DefaultQuery("username", "少林")
username := c.Query("username") //通过query来获取用户传递过来的参数
address := c.Query("address")
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
"username": username,
"address": address,
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}

浏览器端查看:

实例2:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) type Result struct {
Message string `json:"message"`
Code int `json:"code"`
} type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
} func handleUserInfo(c *gin.Context) { username := c.Query("username")
passwd := c.DefaultQuery("passwd", "dkdkdkdkdkdkdkd") //默认值,如果用户没有传递过来值,则为此处定义默认值 var result UserInfo = UserInfo{
UserName: username,
Passwd: passwd,
} result.Code =
result.Message = "success" c.JSON(http.StatusOK, result)
} func main() {
r := gin.Default()
r.GET("/user/info", handleUserInfo) r.Run(":9090")
}

执行结果:

浏览器端查看:

用户不传递参数:

用户传递参数:

2.2 通过路径传递, 比如: /user/search/少林/北京

实例1:

package main

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

func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/user/info/:username/:address", func(c *gin.Context) {
//username := c.DefaultQuery("username", "少林")
username := c.Param("username") //用param方法
address := c.Param("address")
//输出json结果给调用方
c.JSON(, gin.H{
"message": "pong",
"username": username,
"address": address,
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}

执行结果:

浏览器端查看:

实例2:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) type Result struct {
Message string `json:"message"`
Code int `json:"code"`
} type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
} func handleUserParams(c *gin.Context) { username := c.Param("username")
passwd := c.Param("passwd") var result UserInfo = UserInfo{
UserName: username,
Passwd: passwd,
} result.Code =
result.Message = "success" c.JSON(http.StatusOK, result)
} func main() {
r := gin.Default()
r.GET("/user/info/:username/:passwd", handleUserParams) r.Run(":9090")
}

执行结果:

浏览器查看:

2.3 通过表单进行提交, 比如: POST /user/search/

下载postman测试工具,测试api有很多也非常方便。

下载地址: https://www.getpostman.com/apps

代码实例如下:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) type Result struct {
Message string `json:"message"`
Code int `json:"code"`
} type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
} func handleUserInfo(c *gin.Context) { username := c.PostForm("username") //使用postform函数获取表单数据
passwd := c.PostForm("passwd") var result UserInfo = UserInfo{
UserName: username,
Passwd: passwd,
} result.Code =
result.Message = "success" c.JSON(http.StatusOK, result)
} func main() {
r := gin.Default()
r.POST("/user/info", handleUserInfo) //选择post方法 r.Run(":9090")
}

执行结果:

通过postman测试结果:

三、Gin框架处理文件上传

3.1 单个文件上传

package main

import (
"fmt"
"net/http" "github.com/gin-gonic/gin"
) type Result struct {
Message string `json:"message"`
Code int `json:"code"`
} type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
} func handleUpload(c *gin.Context) { file, err := c.FormFile("testfile") //通过formfile方法来获取上传的文件,传入的参数是对上传文件的标识(可以随便起名),也就是要上传的文件的key
if err != nil {
fmt.Printf("upload file failed")
return
} filename := fmt.Sprintf("C:/tmp/%s", file.Filename) //文件保存位置
err = c.SaveUploadedFile(file, filename) //调用c将上传文件保存至指定位置
if err != nil {
fmt.Printf("save file failed, err:%v\n", err)
return
} c.JSON(http.StatusOK, "file upload success") //http.StatusOK就是返回状态码200
} func main() {
r := gin.Default()
r.POST("/file/upload", handleUpload) r.Run(":9090")
}

执行结果:

postman执行结果:

保存文件查看结果:

3.2 多个文件上传

package main

import (
"fmt"
"net/http" "github.com/gin-gonic/gin"
) type Result struct {
Message string `json:"message"`
Code int `json:"code"`
} type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
} func handleMultiUpload(c *gin.Context) { form, err := c.MultipartForm() //多个文件用multipartform方法
if err != nil {
fmt.Printf("upload file failed")
return
} files := form.File["testfile"] //传入文件名的key,其返回值是一个数组
for _, file := range files { //遍历数组,即可把要传入的多个文件都保存起来了
filename := fmt.Sprintf("C:/tmp/%s", file.Filename)
err = c.SaveUploadedFile(file, filename)
if err != nil {
fmt.Printf("save file failed, err:%v\n", err)
return
}
}
c.JSON(http.StatusOK, "file upload success")
} func main() {
r := gin.Default()
r.POST("/files/upload", handleMultiUpload) r.Run(":9090")
}

执行结果:

postman执行结果:

保存文件查看结果:

四、Gin框架路由分组

路由分组做的就是把相同的前缀通过借助group方法实现分组。

实例:

package main

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

func login(ctx *gin.Context) {
ctx.JSON(, gin.H{
"message": "success",
})
}
func submit(ctx *gin.Context) {
ctx.JSON(, gin.H{
"message": "success",
})
}
func main() {
//Default返回一个默认的路由引擎
router := gin.Default()
// Simple group: v1
v1 := router.Group("/v1")
{
v1.GET("/login", login) // 等价于/v1/login
v1.POST("/submit", submit)
}
// Simple group: v2
v2 := router.Group("/v2")
{
v2.POST("/login", login)
v2.POST("/submit", submit) //等价于/v2/submit
}
router.Run(":8080")
}

执行结果:

验证测试:

五、Gin框架参数绑定(方便)

为什么要参数绑定,本质上是方便,提高开发效率

A. 通过反射的机制,自动提取querystring、 form表单、 json、 xml等参数到struct中

B. 通过http协议中的context type,识别是json、 xml或者表单

参考网址:

http://www.zhimengzhe.com/bianchengjiaocheng/qitabiancheng/28966.html

注意:

要绑定一个请求body到某个类型, 可以使用model binding。 目前支持JSON, XML 以及标准from格式 (foo=bar&boo=baz)的绑定。

所有你想要绑定的域(field), 需要你设置对应的绑定标识。 例如, 要绑定到JSON, 则这样声明json:"fieldname"。

使用Bind方法时, Gin会尝试通过Content-Type头部来推定绑定的类型(如json还是form)。而如果你明确知道要绑定的类型, 可以使用BindWith方法。

你也可以指定哪些filed需要绑定。 如果某个filed像这样声明: binding:"required", 那么在进行绑定时如果发现是空值(注: 是请求中不存在该field名?), 当前的请求会失败并收到错误提示。

实例1:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) type UserInfo struct {
UserName string `form:"username" json:"username" binding:"required"` //form表单、json串
Passwd string `form:"passwd" json:"passwd" binding:"required"`
Age int `form:"age" json:"age" binding:"required"`
Sex string `form:"sex" json:"sex" binding:"required"`
} //form
func handleUserInfoForm(c *gin.Context) {
var userInfo UserInfo
err := c.ShouldBind(&userInfo) //直接将结构体的4个参数选项绑定过来,借助ShouldBind
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, userInfo)
}
} //json
func handleUserInfoJson(c *gin.Context) {
var userInfo UserInfo
err := c.ShouldBindJSON(&userInfo)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, userInfo)
}
} //querystring
func handleUserInfoQuery(c *gin.Context) {
var userInfo UserInfo
err := c.ShouldBind(&userInfo)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, userInfo)
}
} func main() {
r := gin.Default() // /v1/user/login
// /v1/user/login2gi
v1Group := r.Group("/v1")
v1Group.POST("/user/infoform", handleUserInfoForm)
v1Group.POST("/user/infojson", handleUserInfoJson)
v1Group.GET("/user/infoquerystring", handleUserInfoQuery)
r.Run(":9090")
}

执行结果:

测试结果:

form:

json:

Querystring:

六、Gin框架渲染

6.1 渲染json

gin.Context.JSON方法进行渲染

代码实例:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) func main() {
r := gin.Default()
// gin.H is a shortcut for map[string]interface{}
r.GET("/someJSON", func(c *gin.Context) {
//第一种方式,自己拼json
c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK}) //gin.H就是一个map的别名,借助gin.H可以去拼接json
}) //第二种:通过定义一个结构体,然后将结构体传给c.JSON,之后会将传递过来的结构体打包成支持json协议的字符串返回给客户端
r.GET("/moreJSON", func(c *gin.Context) {
// You also can use a struct
var msg struct {
Name string `json:"user"`
Message string
Number int
}
msg.Name = "Lena"
msg.Message = "hey"
msg.Number =
// Note that msg.Name becomes "user" in the JSON
c.JSON(http.StatusOK, msg)
})
// Listen and serve on 0.0.0.0:8080
r.Run(":8080")
}

执行结果:

浏览器测试:

6.2 渲染xml

gin.Context.XML方法进行渲染

代码实例1:

package main

import (
"github.com/gin-gonic/gin"
) type Result struct {
Message string `json:"message"`
Code int `json:"code"`
} type UserInfo struct {
Result
UserName string `json:"username"`
Passwd string `json:"passwd"`
} func handleUserInfo(c *gin.Context) { var userInfo = &UserInfo{
UserName: "skkss",
Passwd: "SSSS",
} c.XML(, userInfo) //将结构体传递给c.xml
} func main() {
r := gin.Default()
r.GET("/user/info", handleUserInfo) r.Run(":9090")
}

执行结果:

浏览器测试:

实例2:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) func main() {
r := gin.Default()
r.GET("/moreXML", func(c *gin.Context) {
// You also can use a struct
type MessageRecord struct {
Name string
Message string
Number int
}
var msg MessageRecord
msg.Name = "Lena"
msg.Message = "hey"
msg.Number =
c.XML(http.StatusOK, msg)
})
// Listen and serve on 0.0.0.0:8080
r.Run(":8080")
}

6.3 渲染模板

gin.Context.HTML方法进行渲染

代码实例目录结构:

posts.html:

{{ define "post" }}     <!-- 用于生命要传递的名字,传递给go源码,相当于模板的key -->
<html><h1>
{{ . }}
</h1>
<p>gin.Context.HTML方法进行渲染</p>
</html>
{{ end }}

posts.html

main.go:

package main

import (
"net/http" "github.com/gin-gonic/gin"
) func handleHtml(c *gin.Context) { c.HTML(http.StatusOK, "post", "ksdkfskfkskfsdkfs") //post是html文件定义的名字
} func main() {
r := gin.Default()
r.LoadHTMLGlob("./templates/*") //将模板文件加载进来 r.GET("/user/info", handleHtml) r.Run(":9090")
}

执行结果:

浏览器测试:

实例2:

import (
"net/http" "github.com/gin-gonic/gin"
) func main() {
router := gin.Default()
router.LoadHTMLGlob("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")
}

七、 Gin框架中间件&路由原理

7.1 Gin框架中间件

A. Gin框架允许在请求处理过程中,加入用户自己的钩子函数。这个钩子函数就叫中间件

B. 因此,可以使用中间件处理一些公共业务逻辑,比如耗时统计,日志打印,登陆校验(不可能说每个api都写这些公共逻辑,我们可以将公共逻辑放到中间件中)

7.2 自己编写中间件

实例1:

package main

import (
"fmt"
"net/http"
"time" "github.com/gin-gonic/gin"
) func StatCost(c *gin.Context) { //统计耗时函数,这就是一个中间件
start := time.Now()
fmt.Printf("start stat cost\n")
c.Next() ////等中间件中其他函数先执行(也就是说执行完c.Next其他函数已经执行完了)
lattancy := time.Since(start) //获取耗时
fmt.Printf("process request cost:%d ms\n", lattancy//) } func handleUserInfo(c *gin.Context) { //此请求处理函数会在中间件中进行处理,该函数执行完,才会执行c.Next
fmt.Printf("request start process\n")
time.Sleep( * time.Second)
c.JSON(http.StatusOK, "38333k333")
} func main() {
r := gin.Default()
r.Use(StatCost) //将中间件函数设置(借助use函数)到gin框架,这样gin框架在处理请求时,就会先调用中间件进行处理 r.GET("/user/info", handleUserInfo)
r.Run(":8080")
}

执行结果:

浏览器测试:

实例2:

package main

import (
"log"
"net/http"
"time" "github.com/gin-gonic/gin"
) func StatCost() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
//可以设置一些公共参数
c.Set("example", "")
//等其他中间件先执行
c.Next()
//获取耗时
latency := time.Since(t)
log.Print(latency)
}
}
func main() {
r := gin.New()
r.Use(StatCost())
r.GET("/test", func(c *gin.Context) {
example := c.MustGet("example").(string)
// it would print: "12345"
log.Println(example)
c.JSON(http.StatusOK, gin.H{
"message": "success",
})
})
// Listen and serve on 0.0.0.0:8080
r.Run(":8080")
}

7.3 Gin框架路由介绍

A. 路由部分用的是: http://github.com/julienschmidt/httprouter

B. 对于所有的路由规则, httprouter会构造一颗前缀树

httprouter官网例子:

package main

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

func index(ctx *gin.Context) {
ctx.JSON(, gin.H{
"message": "index",
})
}
func main() {
//Default返回一个默认的路由引擎
router := gin.Default()
router.POST("/", index)
router.POST("/search", index)
router.POST("/support", index)
router.POST("/blog/:post", index)
router.POST("/about", index)
router.POST("/contact", index)
router.Run(":8080")
}

生成的前缀数如下所示:

Go语言基础之20--web编程框架之Gin框架的更多相关文章

  1. Python语言基础07-面向对象编程基础

    本文收录在Python从入门到精通系列文章系列 1. 了解面对对象编程 活在当下的程序员应该都听过"面向对象编程"一词,也经常有人问能不能用一句话解释下什么是"面向对象编 ...

  2. 01 . Go框架之Gin框架从入门到熟悉(路由和上传文件)

    Gin框架简介 Gin是使用Go/Golang语言实现的HTTP Web框架, 接口简洁, 性能极高,截止1.4.0版本,包含测试代码,仅14K, 其中测试代码9K, 也就是说测试源码仅5k左右, 具 ...

  3. Go语言基础之接口(面向对象编程下)

    1 接口 1.1 接口介绍 接口(interface)是Go语言中核心部分,Go语言提供面向接口编程,那么接口是什么? 现实生活中,有许多接口的例子,比如说电子设备上的充电接口,这个充电接口能干什么, ...

  4. Go语言基础之18--接口编程

    一.接口介绍和定义 1.1 接口定义了一个对象的行为规范 A. 只定义规范,不实现 B. 具体的对象需要实现规范的细节 葵花宝典: 接口就是一层封装,1个例子,封装一个返还浏览器内容的接口.为什么不直 ...

  5. 20 Web 编程 - 《Python 核心编程》

  6. 02 . Go框架之Gin框架从入门到熟悉(数据解析和绑定,渲染,重定向,同步异步,中间件)

    数据解析和绑定 json数据解析和绑定 package main import ( "github.com/gin-gonic/gin" "net/http" ...

  7. 03 . Go框架之Gin框架从入门到熟悉(Cookie和Session,数据库操作)

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

  8. Web框架之Gin

    Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...

  9. Web框架之Gin介绍及使用

    Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...

随机推荐

  1. .Net时间运算 - DateTime类,TimeSpan类

    DateTime类是.Net中用于处理时间类型数据的. 一.字段 MaxValue 表示 DateTime 的最大可能值.此字段为只读. MinValue     表示 DateTime 的最小可能值 ...

  2. JQuery利用css()修改样式后 hover失效的解决办法

    执行完代码后发现写在样式表中的hover效果失效,改了好几遍差点重新写函数,后来发现很简单,是优先级的问题,css()中的内容覆盖了之前的样式 只需要在样式后写!important即可解决! .fil ...

  3. 使用HttpClient进行Get通信

    --------------siwuxie095                             首先到 Apache官网 下载相关的库文件     Apache官网:http://www.a ...

  4. 第一次WM_PAINT事件执行前显示白色框 的解决办法

    界面显示前,总是会显示白色或白加黑的窗体, 开始以为是图片加载慢的原因,后来发现这个框是在第一次WM_PAINT执行前显示的. 解决办法很简单,在CreateWindow的时候,加上WS_POPUP样 ...

  5. unity3d 5.6参考手册

    http://www.vfkjsd.cn/unity3d/Manual/index.html http://www.vfkjsd.cn/unity/unity3d.html

  6. 【摘自lvs官网】lvs介绍

    Linux Virtual Server项目的目标 :使用集群技术和Linux操作系统实现一个高性能.高可用的服务器,它具有很好的可伸缩性(Scalability).可靠性(Reliability)和 ...

  7. 客户注册功能,发短信功能分离 通过ActiveMQ实现

    客户注册功能,发短信功能分离 通过ActiveMQ 配置链接工厂, 配置session缓存工厂(引入链接工厂) 2.配置模板对象JmsTemplate 引入缓存工厂    指定消息模式(队列,发布和订 ...

  8. dreamweaver cs5 快捷键

    撤销上一步:ctrl + Z: 回复上一步:ctrl + Y: 代码缩进:左下角(应用原格式)

  9. Cactus在jexus上安装

    在成功安装完Mono和jexus后(强烈建议Mono 4.2.1以上,jexus 5.6.1 以上,本人测试环境就是Mono 4.2.1和jexus 5.6.1) 第一步: 先配置jexus安装目录下 ...

  10. Dapper --Execute

    Dapper-Execute Ececute是一种可被任何IDbConnection类型的对象调用的扩展方法.它可以执行一次或多次命令, 并返回受影响的行数.此方法通常用于执行存储过程.插入.更新.删 ...