##
asong Gin
github:https://github.com/sunsong2020/Golang_Dream/tree/master/Gin/Doc
Golang Gin
Remarks: Only some important documents are posted here, please follow the above method to obtain the full PDF.
2020Gin Framework Chinese Document
@[toc]
installation
Before installing the Gin package, you need to install the Go environment on your computer and set up your workspace.
- First you need to install Go (support version 1.11+), and then use the following Go command to install Gin:
$ go get -u github.com/gin-gonic/gin
- Import the Gin package in your code:
import "github.com/gin-gonic/gin"
- (Optional) If you use
http.StatusOK
constants such as , you need to import thenet/http
package:
import "net/http"
Quick start
# example.go
$ cat example.go
package main
import "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 serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
API example
You can find many ready-made examples in the Gin example repository.
Use GET, POST, PUT, PATCH, DELETE and OPTIONS
func main() {
//logger recovery gin
router := 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)
// 8080 PORT .
router.Run()
// router.Run(":3000") hardcode
}
Routing parameters
func main() {
router := gin.Default()
// handler /user/john /user/ /user
router.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
// , /user/john/ /user/john/send
// /user/john, /user/john/
router.GET("/user/:name/*action", func(c *gin.Context) {
name := c.Param("name")
action := c.Param("action")
message := name + " is " + action
c.String(http.StatusOK, message)
})
//
router.POST("/user/:name/*action", func(c *gin.Context) {
c.FullPath() == "/user/:name/*action" //true
})
router.Run(":8080")
}
Query string parameters
func main() {
router := gin.Default()
// request
// URL: /welcome?firstname=Jane&lastname=Doe
router.GET("/welcome", func(c *gin.Context) {
firstname := c.DefaultQuery("firstname", "Guest")
lastname := c.Query("lastname") // c.Request.URL.Query().Get("lastname")
c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
})
router.Run(":8080")
}
Multipart/Urlencoded form
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")
}
Other examples: query+post form
POST/post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
name=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")
}
operation result:
id: 1234; page: 1; name: manu; message: this_is_great
Map as query string or post form parameter
POST/post?ids[a]=1234&ids[b]=hello HTTP/1.1
Content-Type: application/x-www-form-urlencoded
names[first]=thinkerou&names[second]=tianou
func main() {
router := gin.Default()
router.POST("/post", func(c *gin.Context) {
ids := c.QueryMap("ids")
names := c.PostFormMap("names")
fmt.Printf("ids: %v; names: %v", ids, names)
})
router.Run(":8080")
}
operation result:
ids: map[b:hello a:1234], names: map[second:tianou first:thinkerou]
upload files
Single file
Refer to issue #774 and detailed example code: example code .
Use file.Filename with caution, refer to Content-Disposition on MDN and #1693
The file name of the uploaded file can be customized by the user, so it may contain illegal character strings. For the sake of safety, the file name rules should be unified by the server.
func main() {
router := gin.Default()
// ( 32 MiB)
router.MaxMultipartMemory = 8 << 20 //8 MiB
router.POST("/upload", func(c *gin.Context) {
//single file
file, _ := c.FormFile("file")
log.Println(file.Filename)
//
c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
router.Run(":8080")
}
curl test:
curl -X POST http://localhost:8080/upload/
-F "file=@/Users/appleboy/test.zip"/
-H "Content-Type: multipart/form-data"
Multiple files
Refer to the detailed example: example code.
func main() {
router := gin.Default()
// (default is 32 MiB)
router.MaxMultipartMemory = 8 << 20 //8 MiB
router.POST("/upload", func(c *gin.Context) {
//
form, _ := c.MultipartForm()
files := form.File["upload[]"]
for _, file := range files {
log.Println(file.Filename)
//
c.SaveUploadedFile(file, dst)
}
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
})
router.Run(":8080")
}
curl test:
curl -X POST http://localhost:8080/upload/
-F "upload[]=@/Users/appleboy/test1.zip"/
-F "upload[]=@/Users/appleboy/test2.zip"/
-H "Content-Type: multipart/form-data"
Routing packet
func main() {
router := gin.Default()
//Simple group: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
//Simple group: v2
v2 := router.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}
router.Run(":8080")
}
The default blank Gin without middleware
use:
r := gin.New()
instead
// Logger and Recovery
r := gin.Default()
Use middleware
func main() {
//
r := gin.New()
//
//Logger gin.DefaultWriter GIN_MODE=release.
// gin.DefaultWriter = os.Stdout
r.Use(gin.Logger())
//Recovery panic panic 500
r.Use(gin.Recovery())
//
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
//
//authorized := r.Group("/", AuthRequired())
//
authorized := r.Group("/")
// "authorized"
// AuthRequired()
authorized.Use(AuthRequired())
{
authorized.POST("/login", loginEndpoint)
authorized.POST("/submit", submitEndpoint)
authorized.POST("/read", readEndpoint)
//
testing := authorized.Group("testing")
testing.GET("/analytics", analyticsEndpoint)
}
// 0.0.0.0:8080
r.Run(":8080")
}
How to write to the log file
func main() {
//
gin.DisableConsoleColor()
//
f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
//
//gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
router.Run(":8080")
}
Custom log format
func main() {
router := gin.New()
//LoggerWithFormatter gin.DefaultWriter
// 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")
}
Sample output:
::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET/ping HTTP/1.1 200 122.767 s "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" "
Controlling Log output coloring
By default, the log output on the console should be colored according to the detected TTY.
The log is not colored:
func main() {
//
gin.DisableConsoleColor()
// gin :
//logger recovery (crash-free)
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
router.Run(":8080")
}
Color the log:
func main() {
//
gin.ForceConsoleColor()
// gin :
//logger recovery (crash-free)
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
c.String(200, "pong")
})
router.Run(":8080")
}
Model binding and verification
To bind the request body to the structure, please use model binding. Currently, binding of JSON, XML, YAML and standard form values (foo=bar&boo=baz) is supported.
Gin uses go-playground/validator.v8 to validate the parameters, click here to view the full document here
You need to set the tag on the bound field. For example, if the binding format is json, it needs to be set to json:"fieldname"
In addition, Gin provides two binding methods:
-
Type-Must bind
- Methods-Bind, BindJSON, BindXML, BindQuery, BindYAML, BindHeader
- Behavior - These methods use the bottom
MustBindWith
, if there is an error bound, the following instruction will be aborted requestc.AbortWithError(400, err).SetType(ErrorTypeBind)
, response status code is set to 400, the request headerContent-Type
is settext/plain
;charset=utf-8
. Note that if you try to set the response code after this, a warning will be issued[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422
. If you want to better control the behavior, please use the ShouldBuind method.
-
Type-Should bind
- Methods-ShouldBind, ShouldBindJSON, ShouldBindXML, ShouldBindQuery, ShouldBindYAML, ShouldBindHeader.
- Behavior-These methods are used at the bottom level
ShouldBindWith
. If there is a binding error, an error is returned, and the developer can handle the request and error correctly. When we use the binding method, Gin willContent-Type
infer which binder to use. If you are sure what you are binding, you can useMustBindWith
orBindingWith
.
You can also specify modifiers of specific rules for the field. If a field is binding:"required"
modified and the value of the field is empty when binding, an error will be returned.
// JSON
type Login struct {
User string `form:"user" json:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" xml:"password" binding:"required"`
}
func main() {
router := gin.Default()
//JSON ({"user": "manu", "password": "123"})
router.POST("/loginJSON", func(c *gin.Context) {
var json Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if json.User != "manu" || json.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})
//XML (
// <?xml version="1.0" encoding="UTF-8"?>
// <root>
// <user>user</user>
// <password>123</password>
// </root>)
router.POST("/loginXML", func(c *gin.Context) {
var xml Login
if err := c.ShouldBindXML(&xml); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if xml.User != "manu" || xml.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})
// HTML (user=manu&password=123)
router.POST("/loginForm", func(c *gin.Context) {
var form Login
// content-type
if err := c.ShouldBind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if form.User != "manu" || form.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})
// 0.0.0.0:8080
router.Run(":8080")
}
Example request:
$ curl -v -X POST/
http://localhost:8080/loginJSON/
-H 'content-type: application/json'/
-d '{ "user": "manu" }'
> POST/loginJSON HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.51.0
> Accept: */*
> content-type: application/json
> Content-Length: 18
>
* upload completely sent off: 18 out of 18 bytes
< HTTP/1.1 400 Bad Request
< Content-Type: application/json; charset=utf-8
< Date: Fri, 04 Aug 2017 03:51:31 GMT
< Content-Length: 100
<
{"error":"Key: 'Login.Password' Error:Field validation for 'Password' failed on the 'required' tag"}
Skip verification:
When using the above curl
command to run the above example, an error is returned, because the Password
fields in the example are used binding:"required"
, if we usebinding:"-"
, then it will not report an error. # Run the example.go file and visit 0.0.0.0:8080/ping on the browser (windows access: localhost:8080/ping) $ go run example.go
Public number: Golang DreamWorks
Asong is a Golang development engineer, focusing on Golang related technologies: Golang interview, Beego, Gin, Mysql, Linux, network, operating system, etc., dedicated to Golang development. Welcome to pay attention to the official account: Golang DreamWorks. Study together and progress together.
How to get the document: Directly reply to the backstage of the official account: Gin, you can get the latest Gin Chinese document. The author asong regularly maintains it.
At the same time, upload documents to personal github: github.com/sunsong2020...