[go]gin框架

摘要:
name=mmfuncmain(){r:=gin.Default()r.GET(“/”,func(c*gin.Context){//name:=c.DefaultQuery(“name”,“defaultname”)name:=c.Query(“名称”)c.JSON(200,gin.H{“name”:name})})r.Run()}?name=mm&name=m2funcmin(){r:=gin.Default()r.GET(“/”,func(c*gin.Context){name:=c.QueryArray(“name”)c.JSON(200,gin.H{“name”:名称})})r.Run()}//{//name:[/“mm”,//“m2”//]/}-/mm/22/funcmin(“age”)c.JSON

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
", 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"
",
                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框架》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Atlantis(POJ1151+线段树+扫描线)axios 同时执行多个请求下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#生成简单验证码

我们平时无论是网站登录还是注册,都会频繁的遇到各式各样的验证码 ,其实生成验证码对于C#来说非常简单。 下面就是我学习生成验证码的简单实例。 封装的辅助类代码,如下: 1 using System; 2 using System.Collections.Generic; 3 using System.Drawing; 4 using System...

【失败的尝试】C++中使用string进行switch判断

贴出错误代码: #include <iostream>#include <string>using namespace std;void main(){    string str;    cin>>str;     switch(str)    {    case "ab":        cout<<"o...

在EggJS中使用Sequelize做联表查询

内容转自https://www.jianshu.com/p/078087c69b77,感谢 1.EggJS引用Sequelize 安装sequelize依赖和mysql驱动 cnpm i egg-sequelize mysql2 -S 启用sequelize插件   在config/plugin.js里面添加 sequelize: { enable...

DbHelper

using System;using System.Collections.Generic;using System.Configuration;using System.Data;using System.Data.SqlClient;using System.Linq;using System.Text; namespace Asmkt.Databas...

用 Java 爬美女图片,厉害了。。

目的 爬取搜狗图片上千张美女图片并下载到本地 准备工作 爬取地址:https://pic.sogou.com/pics?query=美女 分析 打开上面的地址,按F12开发者工具 - NetWork - XHR - 页面往下滑动XHR栏出现请求信息如下: Request URL : https://pic.sogou.com/napi/pc/searchL...

熟悉Hbase常用命令及操作

(一) 编程实现以下指定功能,并用Hadoop提供的HBase Shell命令完成相同任务: 列出HBase所有的表的相关信息,例如表名; 在终端打印出指定的表的所有记录数据; 向已经创建好的表添加和删除指定的列族或列; 清空指定的表的所有记录数据; 统计表的行数。 (二)HBase数据库操作 1.现有以下关系型数据库中的表和数据,要求将其转换为适合于HB...