zoukankan      html  css  js  c++  java
  • [go]gin框架

    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}
    
  • 相关阅读:
    2015531 网络攻防 Exp1 PC平台逆向破解(5)M
    2017-2018-1 20155331 嵌入式C语言
    20155330 《网络对抗》 Exp9 web安全基础实践
    20155330 《网络对抗》 Exp8 Web基础
    20155330 《网络对抗》 Exp7 网络欺诈防范
    20155330 《网络对抗》 Exp6 信息搜集与漏洞扫描
    20155330 《网络对抗》 Exp5 MSF基础应用
    20155330 《网络攻防》 Exp4 恶意代码分析
    20155330 《网络攻防》 Exp3 免杀原理与实践
    20155330 《网络对抗》 Exp2 后门原理与实践
  • 原文地址:https://www.cnblogs.com/iiiiiher/p/12014263.html
Copyright © 2011-2022 走看看