gin中文文档

gin example repo

gin参考

gin框架基础使用-梳理版

- 最简单的gin启服务

package main

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

func main() {
r := gin.Default()
r.Run() //端口默认8080
}

RESPONSE RENDERING

context.go

- 返回字符串

func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
body, _ := ioutil.ReadAll(c.Request.Body)
c.String(http.StatusOK, "Put,%s", body)
})
r.Run()
}
- 返回json

func main() {
r := gin.Default()
//返回json
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"name": "mm",
"age": 22,
})
}) //返回map
m := map[string]int{}
m["m1"] = 11
m["m2"] = 12 r.GET("/map", func(c *gin.Context) {
c.JSON(200, m)
}) //返回struct
r.GET("/struct", func(c *gin.Context) {
c.JSON(200, struct {
Name string
Age int
}{"m1", 22})
}) r.Run()
}
- 渲染template和静态文件
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.Static("/static", "./static") r.GET("/", func(c *gin.Context) {
c.HTML(200, "index.html", nil)
})
r.Run()
}

context.go: RESPONSE RENDERING部分源码

- 请求头相关
//设置response status
func (c *Context) Status(code int) //设置response header
func (c *Context) Header(key, value string) //快捷方式 c.Writer.Header().Set(key, value) //获取request header
func (c *Context) GetHeader(key string) string //获取stream的原生数据
func (c *Context) GetRawData() ([]byte, error) //设置response header: Set-Cookie
func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) //获取request的cookie
func (c *Context) Cookie(name string) (string, error) //写入status/response header/content type 并执行渲染
func (c *Context) Render(code int, r render.Render)
c.Status(code)
r.WriteContentType(c.Writer)
c.Writer.WriteHeaderNow()
r.Render(c.Writer) //HTML renders
func (c *Context) HTML(code int, name string, obj interface{}) // IndentedJSON serializes
// SecureJSON serializes
// JSONP serializes // JSON serializes
func (c *Context) JSON(code int, obj interface{})
// AsciiJSON serializes
// PureJSON serializes
// XML serializes
// YAML serializes
// ProtoBuf serializes
func (c *Context) ProtoBuf(code int, obj interface{}) // String writes: the given string into the response body.
func (c *Context) String(code int, format string, values ...interface{}) // Redirect returns a HTTP redirect to the specific location.
func (c *Context) Redirect(code int, location string) - 字符串
// Data writes some data into the body stream and updates the HTTP code.
func (c *Context) Data(code int, contentType string, data []byte) // DataFromReader writes the specified reader into the body stream and updates the HTTP code. - 文件相关
// File writes the specified file into the body stream in a efficient way.
func (c *Context) File(filepath string)
// FileAttachment writes the specified file into the body stream in an efficient way
func (c *Context) FileAttachment(filepath, filename string) - 长连接相关
// SSEvent writes a Server-Sent Event into the body stream.
// Stream sends a streaming response and returns a boolean

INPUT DATA

context.go


- ?name=mm
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
//name := c.DefaultQuery("name", "default name")
name := c.Query("name")
c.JSON(200, gin.H{"name": name}) })
r.Run()
}
?name=mm&name=m2

func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
names := c.QueryArray("name") c.JSON(200, gin.H{"name": names})
})
r.Run()
} //{
// name: [
// "mm",
// "m2"
// ]
//}
- /mm/22/
func main() {
r := gin.Default()
r.GET("/:name/:age", func(c *gin.Context) {
name := c.Param("name")
age := c.Param("age")
c.JSON(200, gin.H{"name": name, "age": age})
})
r.Run()
}
- 收到表单数据 - 获取数据
<body>
<form action="http://localhost:8080/" method="post">
<input type="text" name="name">
<input type="text" name="age">
<input type="submit">
</form>
</body> func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
name := c.PostForm("name")
age := c.PostForm("age")
c.JSON(200, gin.H{"name": name, "age": age})
})
r.Run()
}
- 收到表单数据 - 绑定到结构体
name=m1 age=22 <body>
<form action="http://localhost:8080/" method="post">
<input type="text" name="name">
<input type="text" name="age">
<input type="submit">
</form>
</body> type User struct {
Name string `form:"name" binding:"required"`
Age int `form:"age" binding:"required"`
} func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
var user User
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&user); err == nil {
c.JSON(http.StatusOK, gin.H{
"name": user.Name,
"age": user.Age,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
r.Run()
}
- 收到json数据 - 绑定到结构体
{"name":"m1","age":22} type User struct {
Name string `json:"name" binding:"required"`
Age int `json:"age" binding:"required"`
} func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
var user User
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&user); err == nil {
c.JSON(http.StatusOK, gin.H{
"name": user.Name,
"age": user.Age,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
r.Run()
}
- 收到url数据, 绑定到结构体
?name=mm&age=22 type User struct {
Name string `form:"name" binding:"required"`
Age int `form:"age" binding:"required"`
} func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
var user User
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&user); err == nil {
c.JSON(http.StatusOK, gin.H{
"name": user.Name,
"age": user.Age,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
r.Run()
}
- 收到表单数据 - 绑定到结构体

/?Name=mm&Age=22

type User struct {
Name string `binding:"required"`
Age int `binding:"required"`
} /?Name=mm
type User struct {
Name string `binding:"required"`
Age int //允许age不传, 默认零值
}

context.go: INPUT DATA源码

//返回url的参数, eg:/user/john  /user/:id  则id=="john"

// c.Params.ByName(key) 的快捷方式
// router.GET("/user/:id", func(c *gin.Context) {
// // a GET request to /user/john
// id := c.Param("id") // id == "john"
// }) func (c *Context) Param(key string) string //返回keyed url的查询参数, 如果不存在则返回""
// c.Request.URL.Query().Get(key)的快捷方式 // GET /path?id=1234&name=Manu&value=
// c.Query("id") == "1234"
// c.Query("name") == "Manu"
// c.Query("value") == ""
// c.Query("wtf") == "" func (c *Context) Query(key string) string //返回keyed url的查询参数, 如果不存在,则返回指定的值 // GET /?name=Manu&lastname=
// c.DefaultQuery("name", "unknown") == "Manu"
// c.DefaultQuery("id", "none") == "none"
// c.DefaultQuery("lastname", "none") == "" func (c *Context) DefaultQuery(key, defaultValue string) string func (c *Context) GetQuery(key string) (string, bool) func (c *Context) QueryArray(key string) []string
func (c *Context) GetQueryArray(key string) ([]string, bool) func (c *Context) QueryMap(key string) map[string]string
func (c *Context) GetQueryMap(key string) (map[string]string, bool) func (c *Context) PostForm(key string) string
func (c *Context) GetPostForm(key string) (string, bool)
func (c *Context) DefaultPostForm(key, defaultValue string) string
func (c *Context) GetPostForm(key string) (string, bool) func (c *Context) GetPostFormArray(key string) ([]string, bool)
func (c *Context) GetPostFormArray(key string) ([]string, bool) func (c *Context) PostFormMap(key string) map[string]string
func (c *Context) GetPostFormMap(key string) (map[string]string, bool) func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) func (c *Context) FormFile(name string) (*multipart.FileHeader, error)
func (c *Context) MultipartForm() (*multipart.Form, error)
func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) //根据content-type 绑定engine
func (c *Context) Bind(obj interface{}) error
func (c *Context) BindJSON(obj interface{}) error
func (c *Context) BindXML(obj interface{}) error
c.MustBindWith(obj, binding.BindXML)
func (c *Context) BindQuery(obj interface{}) error
func (c *Context) BindYAML(obj interface{}) error
func (c *Context) BindHeader(obj interface{}) error
func (c *Context) BindUri(obj interface{}) error
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error ...ShouldBind func (c *Context) ClientIP() string
func (c *Context) ContentType() string
func (c *Context) IsWebsocket() bool
func (c *Context) requestHeader(key string) string

路由

- 路由组
func main() {
r := gin.Default() v1 := r.Group("/v1")
{
// /v1/
v1.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"name": "m1"})
})
// /v1/test
v1.GET("/test", func(c *gin.Context) {
c.JSON(200, gin.H{"name": "m1 test"})
})
} v2 := r.Group("/v2")
v2.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"name": "m2"})
})
v2.GET("/test", func(c *gin.Context) {
c.JSON(200, gin.H{"name": "m2 test"})
})
r.Run()
}

gin框架-基础使用

Gin框架返回值

// 返回json

func main() {
r := gin.Default() //方法一: 自己拼接json
// 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})
}) //方法2: 返回结构体对象
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 = 123 // 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")
}
// 渲染html

router.LoadHTMLGlob("templates/*")
router.Static("/static", "./static") func main() {
router := gin.Default() router.LoadHTMLGlob("templates/*") // LoadHTMLFiles只会加载一个文件
router.Static("/static", "./static") //第二个参数相对于执行路径 //渲染静态目录
router.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
router.Run(":8000")
}

Gin框架参数传递

//获取参数 querystring

/user/search?name=mm&age=22

r.GET("/user/search", func(c *gin.Context)
name := c.DefaultQuery("name", "mm") // 赋默认值
name := c.Query("name") func main() {
r := gin.Default()
r.GET("/user/search", func(c *gin.Context) {
name := c.DefaultQuery("name", "mm")
//name := c.Query("name")
age := c.Query("age") //输出json结果给调用方
c.JSON(200, gin.H{
"message": "pong",
"name": name,
"age": age,
})
}) r.Run() // listen and serve on 0.0.0.0:8080
}
// 获取参数 path

/user/search/mm/22
r.GET("/user/search/:name/:age", func(c *gin.Context) name := c.Param("mm") func main() {
r := gin.Default()
r.GET("/user/search/:name/:age", func(c *gin.Context) {
name := c.Param("mm")
age := c.Param("age") //输出json结果给调用方
c.JSON(200, gin.H{
"message": "pong",
"username": username,
"address": address,
})
}) r.Run(":8080") // listen and serve on 0.0.0.0:8080
}
// 获取参数: form提交

r.POST("/user/search", func(c *gin.Context) {
name := c.DefaultPostForm("name", "mm")
name := c.PostForm("name") func main() {
r := gin.Default()
r.POST("/user/search", func(c *gin.Context) {
//name := c.DefaultPostForm("name", "mm")
name := c.PostForm("name")
age := c.PostForm("age")
//输出json结果给调用方
c.JSON(200, gin.H{
"message": "pong",
"name": name,
"age": age,
})
}) r.Run(":8080")
}

// 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 login Login if err := c.ShouldBindJSON(&login); err == nil {
fmt.Printf("login info:%#v\n", login)
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
}) // Example for binding a HTML form (user=manu&password=123)
router.POST("/loginForm", func(c *gin.Context) {
var login Login
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&login); err == nil {
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
}) // Example for binding a HTML querystring (user=manu&password=123)
router.GET("/loginForm", func(c *gin.Context) {
var login Login
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&login); err == nil {
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
}) // Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}

gin Restful

// restful风格

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

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

Gin中间件

//计算请求耗时

func StatCost() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now() //可以设置一些公共参数
c.Set("example", "12345")
//等其他中间件先执行
c.Next()
//获取耗时
latency := time.Since(t)
log.Printf("total cost time:%d us", latency/1000)
}
} func main() {
//r := gin.New()
r := gin.Default()
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()
}
// 从第三方获取数据

func main() {
router := gin.Default()
router.GET("/someDataFromReader", func(c *gin.Context) {
response, err := http.Get("https://raw.githubusercontent.com/gin-gonic/logo/master/color.png")
if err != nil || response.StatusCode != http.StatusOK {
c.Status(http.StatusServiceUnavailable)
return
} reader := response.Body
contentLength := response.ContentLength
contentType := response.Header.Get("Content-Type") extraHeaders := map[string]string{
"Content-Disposition": `attachment; filename="gopher.png"`,
} c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
})
router.Run(":8080")
}

Gin写日志

//写日志到文件

func main() {
// Disable Console Color, you don't need console color when writing the logs to file.
gin.DisableConsoleColor() // Logging to a file.
f, _ := os.Create("/tmp/gin.log") gin.DefaultWriter = io.MultiWriter(f) // Use the following code if you need to write the logs to file and console at the same time.
// gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
//输出json结果给调用方
c.JSON(200, gin.H{
"message": "pong",
})
}) r.Run() // listen and serve on 0.0.0.0:8080
}
// 自定义日志格式

func main() {
router := gin.New() // LoggerWithFormatter 中间件会将日志写入 gin.DefaultWriter
// By default gin.DefaultWriter = os.Stdout
router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { // 你的自定义格式
return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
param.ClientIP,
param.TimeStamp.Format(time.RFC1123),
param.Method,
param.Path,
param.Request.Proto,
param.StatusCode,
param.Latency,
param.Request.UserAgent(),
param.ErrorMessage,
)
}))
router.Use(gin.Recovery()) router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
}) router.Run(":8080")
}

获取header和body

func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
for k, v := range c.Request.Header {
fmt.Println(k, v)
}
body, _ := ioutil.ReadAll(c.Request.Body)
fmt.Println(string(body))
c.JSON(200, gin.H{"name": "m1"})
})
r.Run()
} //Content-Type [application/json]
//Cache-Control [no-cache]
//Content-Length [22]
//User-Agent [PostmanRuntime/7.21.0]
//Accept [*/*]
//Postman-Token [471de3df-7a5c-4e22-a92f-33eacd076722]
//Accept-Encoding [gzip, deflate]
//Connection [keep-alive] //{"name":"m1","age":22}

[go]gin框架的更多相关文章

  1. 基于gin框架和jwt-go中间件实现小程序用户登陆和token验证

    本文核心内容是利用jwt-go中间件来开发golang webapi用户登陆模块的token下发和验证,小程序登陆功能只是一个切入点,这套逻辑同样适用于其他客户端的登陆处理. 小程序登陆逻辑 小程序的 ...

  2. gin框架使用注意事项

    gin框架使用注意事项 本文就说下这段时间我在使用gin框架过程中遇到的问题和要注意的事情. 错误处理请求返回要使用c.Abort,不要只是return 当在controller中进行错误处理的时候, ...

  3. Gin框架源码解析

    Gin框架源码解析 Gin框架是golang的一个常用的web框架,最近一个项目中需要使用到它,所以对这个框架进行了学习.gin包非常短小精悍,不过主要包含的路由,中间件,日志都有了.我们可以追着代码 ...

  4. gin框架学习手册

    前言 gin框架是go语言的一个框架,框架的github地址是:https://github.com/gin-gonic/gin 转载本文,请标注原文地址:https://www.cnblogs.co ...

  5. go的gin框架从请求中获取参数的方法

    前言: go语言的gin框架go里面比较好的一个web框架, github的start数超过了18000.可见此框架的可信度 如何获取请求中的参数 假如有这么一个请求: POST   /post/te ...

  6. Go语言基础之20--web编程框架之Gin框架

    一.Gin框架介绍 1.1 简介 A. 基于httprouter开发的web框架. http://github.com/julienschmidt/httprouter B. 提供Martini风格的 ...

  7. Gin 框架 - 安装和路由配置

    目录 概述 Gin 安装 路由配置 推荐阅读 概述 看下 Gin 框架的官方介绍: Gin 是一个用 Go (Golang) 编写的 web 框架. 它是一个类似于 martini 但拥有更好性能的 ...

  8. Gin 框架 - 使用 logrus 进行日志记录

    目录 概述 日志格式 Logrus 使用 推荐阅读 概述 上篇文章分享了 Gin 框架的路由配置,这篇文章分享日志记录. 查了很多资料,Go 的日志记录用的最多的还是 github.com/sirup ...

  9. [系列] Gin框架 - 数据绑定和验证

    目录 概述 推荐阅读 概述 上篇文章分享了 Gin 框架使用 Logrus 进行日志记录,这篇文章分享 Gin 框架的数据绑定与验证. 有读者咨询我一个问题,如何让框架的运行日志不输出控制台? 解决方 ...

  10. Gin框架 - 自定义错误处理

    目录 概述 错误处理 自定义错误处理 panic 和 recover 推荐阅读 概述 很多读者在后台向我要 Gin 框架实战系列的 Demo 源码,在这里再说明一下,源码我都更新到 GitHub 上, ...

随机推荐

  1. Cannot determine value type from string 'xxxxxx'

    Cannot determine value type from string 'xxxxxx' 查了一下,意思就是字段和属性名没有对上. 反复查看代码,字段名和属性名一致. 最后翻阅资料得知是因为构 ...

  2. Win10系统更新提示错误0xc1900403的解决方法

    Win10系统自从发布上线以来,一直有不断地进行更新,而每次更新也给我们用户带来了大大小小不同的惊喜.但是近来一些用户反应说Win10系统更新一直失败,并出现0xc1900403的错误代码提示. 对于 ...

  3. json —— pickle 的序列化和反序列化

    前言json的序列化和反序列化 1, json 只能序列化简单的数据类型,如,列表,字典,字符串,等简单的类型,不能序列化复杂的类型. 2, json 是支持所有的语言的,多以我们跨语言的时候都是用j ...

  4. webpack中shimming的概念

    在webpack打包过程中会去做一些代码上的兼容,或者打包过程的兼容,比如之前使用过的babel-polyfill这个工具,他解决了es6代码在低版本浏览器的兼容.这就是webpack中的垫片.他解决 ...

  5. 用.htaccess 禁止IP访问

    用.htaccess 禁止某IP访问 Order Allow,Deny Allow from all Deny from 1.1.1.1 2.2.2.2 3.3.3.3 允许所有,禁止xxxx,请将里 ...

  6. linux目录太长怎么办?分享一点小技巧

    在linux使用cd的时候,可能会遇到目录比较深的时候,这个时候总是cd一个很长的目录会很麻烦,那有没有什么比较方便的方法呢? 若是在两个目录中来回切换,这个时候可以使用cd - 这个命令,可以完成在 ...

  7. Hadoop动态增加节点与删除节点

    Hadoop的全分布式安装网上也很多教程,踩过很多坑,整理不出来了……赶紧把增加删除节点留住. 均衡数据 (1)设置数据传输带宽为64M(默认值比较低) hdfs dfsadmin -setBalan ...

  8. ASP.Net页面生存周期、Page_Load方法

    一.ASP.Net Web应用程序中的请求处理过程 二. http模块生命周期: 三.Asp.NET页面生命周期 1.阶段 阶段 说明 请求页面(Page Request) 严格地说,这个阶段不是页面 ...

  9. pycharm分辨率&清晰度

    三个月前换了新电脑,安装pycharm.又换了新的大屏幕. pycharm界面拖到大屏上时,字大小和字体都没有变化,清晰度低了很多,就像打了一层薄薄的马赛克一样.拖回到原本的屏幕又清晰了. 一直以为是 ...

  10. Consul概述

    环境安装 1.下载consul 官网https://www.consul.io/downloads.html下载对应版本的consul:本文以Windows-64版本为例 2.配置到系统环境变量 C: ...