翻译自: https://github.com/gin-gonic/gin/blob/develop/README.md

Gin Web框架





Gin是用Golang实现的一种Web框架。基于 httprouter,它提供了相似martini但更好性能(路由性能约快40倍)的API服务. 假设你希望构建一个高性能的生产环境,你会喜欢上使用 Gin。

$ cat test.go
package mainimport "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() // listen and server on 0.0.0.0:8080
}

基准測试

Gin基于HttpRouter的这个定制版本号来构建。

查看所有測试

Benchmark name (1) (2) (3) (4)
BenchmarkAce_GithubAll 10000 109482 13792 167
BenchmarkBear_GithubAll 10000 287490 79952 943
BenchmarkBeego_GithubAll 3000 562184 146272 2092
BenchmarkBone_GithubAll 500 2578716 648016 8119
BenchmarkDenco_GithubAll 20000 94955 20224 167
BenchmarkEcho_GithubAll 30000 58705 0 0
BenchmarkGin_GithubAll 30000 50991 0 0
BenchmarkGocraftWeb_GithubAll 5000 449648 133280 1889
BenchmarkGoji_GithubAll 2000 689748 56113 334
BenchmarkGoJsonRest_GithubAll 5000 537769 135995 2940
BenchmarkGoRestful_GithubAll 100 18410628 797236 7725
BenchmarkGorillaMux_GithubAll 200 8036360 153137 1791
BenchmarkHttpRouter_GithubAll 20000 63506 13792 167
BenchmarkHttpTreeMux_GithubAll 10000 165927 56112 334
BenchmarkKocha_GithubAll 10000 171362 23304 843
BenchmarkMacaron_GithubAll 2000 817008 224960 2315
BenchmarkMartini_GithubAll 100 12609209 237952 2686
BenchmarkPat_GithubAll 300 4830398 1504101 32222
BenchmarkPossum_GithubAll 10000 301716 97440 812
BenchmarkR2router_GithubAll 10000 270691 77328 1182
BenchmarkRevel_GithubAll 1000 1491919 345553 5918
BenchmarkRivet_GithubAll 10000 283860 84272 1079
BenchmarkTango_GithubAll 5000 473821 87078 2470
BenchmarkTigerTonic_GithubAll 2000 1120131 241088 6052
BenchmarkTraffic_GithubAll 200 8708979 2664762 22390
BenchmarkVulcan_GithubAll 5000 353392 19894 609
BenchmarkZeus_GithubAll 2000 944234 300688 2648

(1): 总反复次数
(2): 单次请求耗时 (ns/op)
(3): 堆内存大小 (B/op)
(4): 单次请求内存分配数 (allocs/op)

Gin v1. stable

  • [x] 零分配路由.
  • [x] 从路由到写请求, 依旧为最快的路由器和框架.
  • [x] 完备的单元測试套件.
  • [x] Battle tested.(?

    )

  • [x] API冻结, 新的release版不会影响现有的代码.

高速開始

  1. 下载并安装Gin:

    $ go get github.com/gin-gonic/gin
  2. 在代码中import进来:

    import "github.com/gin-gonic/gin"
  3. (可选) Import net/http. 假设用到诸如 http.StatusOK的常量, 须要引入该包:

    import "net/http"

API演示样例

使用 GET, POST, PUT, PATCH, DELETE 以及 OPTIONS

func main() {// Creates a gin router with default middleware:// logger and recovery (crash-free) middlewarerouter := gin.Default()router.GET("/someGet", getting)router.POST("/somePost", posting)router.PUT("/somePut", putting)router.DELETE("/someDelete", deleting)router.PATCH("/somePatch", patching)router.HEAD("/someHead", head)router.OPTIONS("/someOptions", options)// By default it serves on :8080 unless a// PORT environment variable was defined.router.Run()// router.Run(":3000") for a hard coded port
}

路径參数

func main() {router := gin.Default()// This handler will match /user/john but will not match neither /user/ or /userrouter.GET("/user/:name", func(c *gin.Context) {name := c.Param("name")c.String(http.StatusOK, "Hello %s", name)})// However, this one will match /user/john/ and also /user/john/send// If no other routers match /user/john, it will redirect to /user/john/router.GET("/user/:name/*action", func(c *gin.Context) {name := c.Param("name")action := c.Param("action")message := name + " is " + actionc.String(http.StatusOK, message)})router.Run(":8080")
}

查询字符串參数

func main() {router := gin.Default()// Query string parameters are parsed using the existing underlying request object.// The request responds to a url matching:  /welcome?firstname=Jane&lastname=Doerouter.GET("/welcome", func(c *gin.Context) {firstname := c.DefaultQuery("firstname", "Guest")lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")c.String(http.StatusOK, "Hello %s %s", firstname, lastname)})router.Run(":8080")
}

Multipart/Urlencoded表单提交

func main() {router := gin.Default()router.POST("/form_post", func(c *gin.Context) {message := c.PostForm("message")nick := c.DefaultPostForm("nick", "anonymous")c.JSON(200, gin.H{"status":  "posted","message": message,"nick":    nick,})})router.Run(":8080")
}

很多其它演示样例: 查询參数 + POST表单提交

POST /post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencodedname=manu&message=this_is_great
func main() {router := gin.Default()router.POST("/post", func(c *gin.Context) {id := c.Query("id")page := c.DefaultQuery("page", "0")name := c.PostForm("name")message := c.PostForm("message")fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message)})router.Run(":8080")
}
id: 1234; page: 1; name: manu; message: this_is_great

很多其它演示样例: 上传文件

參考问题 #548.

func main() {router := gin.Default()router.POST("/upload", func(c *gin.Context) {file, header , err := c.Request.FormFile("upload")filename := header.Filenamefmt.Println(header.Filename)out, err := os.Create("./tmp/"+filename+".png")if err != nil {log.Fatal(err)}defer out.Close()_, err = io.Copy(out, file)if err != nil {log.Fatal(err)}})router.Run(":8080")
}

分组路由

func main() {router := gin.Default()// Simple group: v1v1 := router.Group("/v1"){v1.POST("/login", loginEndpoint)v1.POST("/submit", submitEndpoint)v1.POST("/read", readEndpoint)}// Simple group: v2v2 := router.Group("/v2"){v2.POST("/login", loginEndpoint)v2.POST("/submit", submitEndpoint)v2.POST("/read", readEndpoint)}router.Run(":8080")
}

不使用中间件, 使用Gin默认配置

使用

r := gin.New()

来取代

r := gin.Default()

使用中间件

func main() {// Creates a router without any middleware by defaultr := gin.New()// Global middlewarer.Use(gin.Logger())r.Use(gin.Recovery())// Per route middleware, you can add as many as you desire.r.GET("/benchmark", MyBenchLogger(), benchEndpoint)// Authorization group// authorized := r.Group("/", AuthRequired())// exactly the same as:authorized := r.Group("/")// per group middleware! in this case we use the custom created// AuthRequired() middleware just in the "authorized" group.authorized.Use(AuthRequired()){authorized.POST("/login", loginEndpoint)authorized.POST("/submit", submitEndpoint)authorized.POST("/read", readEndpoint)// nested grouptesting := authorized.Group("testing")testing.GET("/analytics", analyticsEndpoint)}// Listen and server on 0.0.0.0:8080r.Run(":8080")
}

model binding与验证

要绑定一个请求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名?), 当前的请求会失败并收到错误提示。

// Binding from JSON
type Login struct {User     string `form:"user" json:"user" binding:"required"`Password string `form:"password" json:"password" binding:"required"`
}func main() {router := gin.Default()// Example for binding JSON ({"user": "manu", "password": "123"})router.POST("/loginJSON", func(c *gin.Context) {var json Loginif c.BindJSON(&json) == nil {if json.User == "manu" && json.Password == "123" {c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})} else {c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})}}})// Example for binding a HTML form (user=manu&password=123)router.POST("/loginForm", func(c *gin.Context) {var form Login// This will infer what binder to use depending on the content-type header.if c.Bind(&form) == nil {if form.User == "manu" && form.Password == "123" {c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})} else {c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})}}})// Listen and server on 0.0.0.0:8080router.Run(":8080")
}

Multipart/Urlencoded表单请求方式的绑定

package mainimport ("github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding"
)type LoginForm struct {User     string `form:"user" binding:"required"`Password string `form:"password" binding:"required"`
}func main() {router := gin.Default()router.POST("/login", func(c *gin.Context) {// you can bind multipart form with explicit binding declaration:// c.BindWith(&form, binding.Form)// or you can simply use autobinding with Bind method:var form LoginForm// in this case proper binding will be automatically selectedif c.Bind(&form) == nil {if form.User == "user" && form.Password == "password" {c.JSON(200, gin.H{"status": "you are logged in"})} else {c.JSON(401, gin.H{"status": "unauthorized"})}}})router.Run(":8080")
}

使用下面命令測试:

$ curl -v --form user=user --form password=password http://localhost:8080/login

XML和JSON的渲染

func main() {r := gin.Default()// gin.H is a shortcut for map[string]interface{}r.GET("/someJSON", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})})r.GET("/moreJSON", func(c *gin.Context) {// You also can use a structvar msg struct {Name    string `json:"user"`Message stringNumber  int}msg.Name = "Lena"msg.Message = "hey"msg.Number = 123// Note that msg.Name becomes "user" in the JSON// Will output  :   {"user": "Lena", "Message": "hey", "Number": 123}c.JSON(http.StatusOK, msg)})r.GET("/someXML", func(c *gin.Context) {c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})})// Listen and server on 0.0.0.0:8080r.Run(":8080")
}

处理静态文件的请求

func main() {router := gin.Default()router.Static("/assets", "./assets")router.StaticFS("/more_static", http.Dir("my_file_system"))router.StaticFile("/favicon.ico", "./resources/favicon.ico")// Listen and server on 0.0.0.0:8080router.Run(":8080")
}

HTML模板渲染

Using LoadHTMLTemplates()

func main() {router := gin.Default()router.LoadHTMLGlob("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")
}

templates/index.tmpl

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

使用不同路径下但同样文件名称的模板

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")
}

templates/posts/index.tmpl

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

templates/users/index.tmpl

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

你也能够使用自己的渲染模板

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

重定向

实现HTTP重定向并不麻烦:

r.GET("/test", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")
})

内部或外部的地址都是支持的。

定制中间件

func Logger() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()// Set example variablec.Set("example", "12345")// before requestc.Next()// after requestlatency := time.Since(t)log.Print(latency)// access the status we are sendingstatus := c.Writer.Status()log.Println(status)}
}func main() {r := gin.New()r.Use(Logger())r.GET("/test", func(c *gin.Context) {example := c.MustGet("example").(string)// it would print: "12345"log.Println(example)})// Listen and server on 0.0.0.0:8080r.Run(":8080")
}

使用 BasicAuth() 中间件

// simulate some private data
var secrets = gin.H{"foo":    gin.H{"email": "foo@bar.com", "phone": "123433"},"austin": gin.H{"email": "austin@example.com", "phone": "666"},"lena":   gin.H{"email": "lena@guapa.com", "phone": "523443"},
}func main() {r := gin.Default()// Group using gin.BasicAuth() middleware// gin.Accounts is a shortcut for map[string]stringauthorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{"foo":    "bar","austin": "1234","lena":   "hello2","manu":   "4321",}))// /admin/secrets endpoint// hit "localhost:8080/admin/secretsauthorized.GET("/secrets", func(c *gin.Context) {// get user, it was set by the BasicAuth middlewareuser := c.MustGet(gin.AuthUserKey).(string)if secret, ok := secrets[user]; ok {c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret})} else {c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("})}})// Listen and server on 0.0.0.0:8080r.Run(":8080")
}

中间件中的Goroutines

在一个middleware或handler中使用goroutine时, 你不能直接使用源gin.Context, 而仅仅能使用它的一份仅仅读拷贝。

func main() {r := gin.Default()r.GET("/long_async", func(c *gin.Context) {// create copy to be used inside the goroutinecCp := c.Copy()go func() {// simulate a long task with time.Sleep(). 5 secondstime.Sleep(5 * time.Second)// note that you are using the copied context "cCp", IMPORTANTlog.Println("Done! in path " + cCp.Request.URL.Path)}()})r.GET("/long_sync", func(c *gin.Context) {// simulate a long task with time.Sleep(). 5 secondstime.Sleep(5 * time.Second)// since we are NOT using a goroutine, we do not have to copy the contextlog.Println("Done! in path " + c.Request.URL.Path)})// Listen and server on 0.0.0.0:8080r.Run(":8080")
}

自己定义HTTP配置

直接使用http.ListenAndServe()。 演示样例:

func main() {router := gin.Default()http.ListenAndServe(":8080", router)
}

或者

func main() {router := gin.Default()s := &http.Server{Addr:           ":8080",Handler:        router,ReadTimeout:    10 * time.Second,WriteTimeout:   10 * time.Second,MaxHeaderBytes: 1 << 20,}s.ListenAndServe()
}

平滑重新启动或关闭

是否须要平滑重新启动或关闭你的服务?有下面这些方式能够实现。

我们能够用 fvbock/endless来替换默认的方法 ListenAndServe,详情请參考#296。

router := gin.Default()
router.GET("/", handler)
// [...]
endless.ListenAndServe(":4242", router)

或者, 除使用endless之外的方法:

  • manners: 一种平滑关闭自己的Go HTTP服务。

转载于:https://www.cnblogs.com/jzssuanfa/p/7268675.html

Gin Web框架简单介绍相关推荐

  1. Web Services简单介绍

    Web Services简单介绍 Web Services入门 一.Web Services简介 1.什么是Web Services? Web Services 是应用程序组件 Web Service ...

  2. Django - Django框架 简单介绍

    Django框架 简单介绍 本文地址: http://blog.csdn.net/caroline_wendy/article/details/29172271 1. 介绍 Django是一个开放源码 ...

  3. 【修真院Java小课堂】Tiles框架简单介绍

    大家好,我是IT修真院上海分院第6期的学员,一枚正直纯洁善良的程序员 今天给大家分享一下,Tiles框架简单介绍 Tiles框架简单介绍 背景介绍 什么是Tiles Tiles 是一种JSP布局框架, ...

  4. soul框架简单介绍与设计模式分析

    soul框架简单介绍与设计模式分析 1. 初识 1.1 查看官网文档了解 1.2. 目标: 2. 分析源码 2.1. 网关的实现原理 2.1.1. 跨域请求问题 2.1.2. 网关请求处理 2.1.3 ...

  5. Rebound动画框架简单介绍

    Rebound动画框架简单介绍 Android菜鸟一枚,有不对的地方希望大家指出,谢谢. 最近在接手了一个老项目,发现里面动画框架用的是facebook中的Rebound框架,由于以前没听说过,放假时 ...

  6. Go gin web框架介绍

    gin框架介绍 一.gin框架介绍 gin是用go语言开发的一个web框架,简单易用,是一个轻量级框架. 二.为什么选择gin 1.运行响应非常快 2.快速开发 3.文档齐全 4.社区活跃 三.特性 ...

  7. Spring 框架简单介绍

    考虑到你可能不熟悉 Spring,我这里对它做下简单介绍.我们常说的 Spring 框架,是指 Spring Framework 基础框架.Spring Framework 是整个 Spring 生态 ...

  8. 玩转人工智能(3)常用的大数据框架简单介绍

    时光不老,我们不散. 讲大数据框架前,简单的介绍下大数据的文化.信息时代人类社会的进步得益于分享和开源.大数据时代属于信息时代的第三代发展阶段(2001年到2011年可以认为是CT行业的黄金期,200 ...

  9. Go Gin web框架的路由原理及中间件原理

    一.Gin框架的路由原理: 参考: go路由httprouter中的压缩字典树算法图解及c++实现 Golang-gin框架路由原理 首先了解下什么是路由? 简而言之,http路由即是一条http请求 ...

  10. python微型web框架flask介绍

    Flask是一个基于python的,微型web框架.之所以被称为微型是因为其核心非常简单,同时具有很强的扩展能力.它几乎不给使用者做任何技术决定. 安装flask时应该注意其必须的几个支持包比如Jin ...

最新文章

  1. 8086内存分段理解
  2. python迭代数据类型_在大型数据集上自动迭代推断数据类型和最小项大小
  3. 使用jquery处理数据时要注意的问题
  4. Linux中sysstat服务,Linux 性能优化工具包 sysstat 以及 sysstat 服务
  5. 学习java技术有前途吗?当然有前途
  6. 81.游戏项目-物体任意角度飞行和停止
  7. 【Qt】Qt5.12版本编译Oracle驱动教程
  8. ubuntu - 如何以root身份使用图形界面管理文件?
  9. java io流操作_十个Demo进行讲解Java中IO流的常用操作~
  10. lua系列之 lua-cjson模块安装报错问题解决
  11. python从键盘输入一个字符串、将小写字母_# 每日一道面试题 # 从键盘输入一个字符串,将小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存。...
  12. 工业机器人综合教学实训平台
  13. 删除服务器远程桌面痕迹,清除3389连接后留下的日志,清除3389远程桌面连接记录...
  14. echarts柱状图及阴影偏移
  15. java开源项目地址
  16. NVIDIA Studio和Game Ready区别
  17. Redis之惰性删除
  18. 《游戏机制——高级游戏设计技术》一2.4 渐进型游戏
  19. Android手电筒介绍
  20. 《SQL与关系数据库理论——如何编写健壮的SQL代码》一3.7 TABLE_DUM和TABLE_DEE

热门文章

  1. Kubernetes 抢占调度Preempt机制源码深入剖析-Kubernetes商业环境实战
  2. 常见的特殊字符和HTML之间的对应关系~
  3. Java中RMI远程调用demo
  4. pat 1006. 换个格式输出整数 (15)
  5. 求数组子序列和最大值
  6. HashMap的工作原理深入再深入
  7. 如何清除你的DNS缓存
  8. SQL Server 2008 Service Broker
  9. Unstated浅析
  10. 第四周任务:wordCountPro