Go语言基础之20--web编程框架之Gin框架
一、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框架的更多相关文章
- Python语言基础07-面向对象编程基础
本文收录在Python从入门到精通系列文章系列 1. 了解面对对象编程 活在当下的程序员应该都听过"面向对象编程"一词,也经常有人问能不能用一句话解释下什么是"面向对象编 ...
- 01 . Go框架之Gin框架从入门到熟悉(路由和上传文件)
Gin框架简介 Gin是使用Go/Golang语言实现的HTTP Web框架, 接口简洁, 性能极高,截止1.4.0版本,包含测试代码,仅14K, 其中测试代码9K, 也就是说测试源码仅5k左右, 具 ...
- Go语言基础之接口(面向对象编程下)
1 接口 1.1 接口介绍 接口(interface)是Go语言中核心部分,Go语言提供面向接口编程,那么接口是什么? 现实生活中,有许多接口的例子,比如说电子设备上的充电接口,这个充电接口能干什么, ...
- Go语言基础之18--接口编程
一.接口介绍和定义 1.1 接口定义了一个对象的行为规范 A. 只定义规范,不实现 B. 具体的对象需要实现规范的细节 葵花宝典: 接口就是一层封装,1个例子,封装一个返还浏览器内容的接口.为什么不直 ...
- 20 Web 编程 - 《Python 核心编程》
- 02 . Go框架之Gin框架从入门到熟悉(数据解析和绑定,渲染,重定向,同步异步,中间件)
数据解析和绑定 json数据解析和绑定 package main import ( "github.com/gin-gonic/gin" "net/http" ...
- 03 . Go框架之Gin框架从入门到熟悉(Cookie和Session,数据库操作)
Cookie Cookie是什么 HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出 Cookie就是解决HTTP协议无状态的方案之一,中文是小 ...
- Web框架之Gin
Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...
- Web框架之Gin介绍及使用
Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...
随机推荐
- android viewpage解决嵌套
子viewpage 自定义 写法一: public class ChildViewPager extends ViewPager{ /** 触摸时按下的点 **/ PointF downP = new ...
- 关于taskaffinity属性的作用
意味着这activity更喜欢哪个TESK,具体见下方说明 当一个包含FLAG_ACTIVITY_NEW_TASK标志的intent启动一个activity时. 一个新的activity,默认地启动到 ...
- 业务逻辑:shiro框架的功能实现
思路:分别在web.xml配置过滤器以及在applicationContext.xml去配置 实现步骤:1.在pom.xml里引入shiro的坐标 2.在web.xml里配置shiro过滤器 3.在a ...
- 连接Excel数据库
SQL语法:http://www.w3school.com.cn/sql/sql_syntax.asp Ctrl键拖(也就是复制) 先输入1,2,然后下拉 一.问题的提出 在ASP编程中会遇到很多大大 ...
- 防恶意解析,禁止用IP访问网站的Apache设置 修改 httpd.conf 实现
一般来说,网站可以用域名和IP来访问.你的网站可以通过IP直接访问,本来这没什么问题,但是会有些隐患: 由于搜索引擎也会收录你的IP地址的页面,所以同一个页面搜索引擎会重复收录,造成页面的权重不如单个 ...
- 《Maven实战》笔记-10-灵活的构建
一.灵活构建的意义 一个优秀的构建系统必须足够灵活,它应该能够让项目在不同的环境下都能成功地构建.例如,典型的项目都会有开发环境.测试环境和产品环境,这些环境的数据库配置不尽相同,那么项目构建的时候就 ...
- java求几个数字的和输出详细步骤
设计思想:要求几个数字的和,就要把输入的字符串转换成浮点型,然后求和再输出. 程序流程图: 程序源代码: //此程序用于从命令行接收多个数字,就和并输出. //作者:赵东睿 //2015.9.26 p ...
- [译]Javascript中的函数
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- WCF寄宿控制台.WindowsService.WinFrom.WebAPI寄宿控制台和windows服务
先建立wcf类库.会默认生成一些试用代码.如下: public class Service1 { public string GetData(int value) { return string.Fo ...
- jQuery的选择器+实例
返回目录 jQuery的冒号选择器 表单 :input :text :password :radio :checkbox :submit :image :reset :button :file :h ...