• [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}
    
  • 相关阅读:
    [翻译] DZNSegmentedControl
    GONMarkupParser的使用
    使用@selector模仿代理功能降低代码耦合度
    编译并导入OpenSSL
    [翻译] TLTagsControl
    [控件] BookTextView
    [控件] AngleGradientView
    【转】jQuery属性过滤选择器
    【转】ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践
    【转】PHP----JS相互调用
  • 原文地址:https://www.cnblogs.com/iiiiiher/p/12014263.html
Copyright © 2020-2023  润新知