review
In the previous section, we used the Gin framework to quickly build an interface for GET requests. Today, we will learn how to GET routes and parameters.
Request verb
Students who are familiar with RESTful should know that RESTful is a design style and development mode of network applications. Each URI represents a resource. The client uses POST, DELETE, PUT and GET to add, DELETE and query resources.
Similarly, in addition to these four verbs, the Gin framework provides us with PATCH, OPTION, HEAD, etc. for details, please refer to the irouts interface of the rendergroup.go file.
type IRoutes interface { Use(...HandlerFunc) IRoutes Handle(string, string, ...HandlerFunc) IRoutes Any(string, ...HandlerFunc) IRoutes GET(string, ...HandlerFunc) IRoutes POST(string, ...HandlerFunc) IRoutes DELETE(string, ...HandlerFunc) IRoutes PATCH(string, ...HandlerFunc) IRoutes PUT(string, ...HandlerFunc) IRoutes OPTIONS(string, ...HandlerFunc) IRoutes HEAD(string, ...HandlerFunc) IRoutes StaticFile(string, string) IRoutes Static(string, string) IRoutes StaticFS(string, http.FileSystem) IRoutes }
Because RenterGroup implements all the request verbs defined by IRoutes, and the Engine type returned by gin.Default inherits RenterGroup, it is very simple to use. You only need to instantiate the object through gin.Default, and then all the routing operations can be used through the object.
func main() { router := gin.Default() router.POST("/article", func(c *gin.Context) { c.String(200, "article post") }) router.DELETE("/article", func(c *gin.Context) { c.String(200, "article delete") }) router.PUT("/article", func(c *gin.Context) { c.String(200, "article put") }) router.GET("/article", func(c *gin.Context) { c.String(200, "article get") }) router.Run() }
The first parameter of the request verb is the request path, and the second parameter is the function used for logical processing, which can be anonymous or the function name defined elsewhere. Different request verbs can define the same path, only need to switch the verbs to enter the corresponding processing logic.
curl -X PUT http://localhost:8080/article curl -X POST http://localhost:8080/article curl -X GET http://localhost:8080/article curl -X DELETE http://localhost:8080/article
Routing parameters
There are two types of GET requests: one is to add "name=pingye" after the URL, which has a parameter name, and the other is to directly add the parameter value / article/1 in the path, which has no parameter name, so it is necessary to parse the parameter in the code.
protocol://hostname:[port]/path/[query]#fragment
Let's first look at how to play with the parameter value of routing. Here is a question, how to use Gin to get the parameter value 1 of the following link.
The implementation method is very simple. You only need to set a placeholder in the route: id. the colon is the flag of the placeholder. The parameter name after the colon can be customized. Gin will match the route with the request address. If the match is successful, 1 will be assigned as the placeholder: id. you only need to call c.Param to get the id value.
router.GET("/article/:id", func(c *gin.Context) { id := c.Param("id") c.String(200, id) })
However, there is a problem with the: id placeholder. If the id parameter value is null, there will be a 404 error prompt.
Then Gin provides another placeholder * id, which can be used to get a null value.
router.GET("/article/*id", func(c *gin.Context) { id := c.Param("id") c.String(200, id) })
General parameter
In addition to the parameter values carried by the route, next we look at the traditional GET method.
http://localhost:8080/welcome?firstname=Jane&lastname=Doe
You can get the parameters after the question mark through the c.Query or c.DefaultQuery methods.
router.GET("/welcome", func(c *gin.Context) { firstname := c.DefaultQuery("firstname", "pingyeaa") lastname := c.Query("lastname") c.String(200, firstname+" "+lastname) })
In the end, both of them call the GetQuery method. The only difference is that DefaultQuery handles the default value.
func (c *Context) DefaultQuery(key, defaultValue string) string { if value, ok := c.GetQuery(key); ok { return value } return defaultValue } func (c *Context) Query(key string) string { value, _ := c.GetQuery(key) return value }
Form parameter
The form content submitted from HTML can also be easily obtained.
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, }) })
curl -d "message=pingye" http://localhost:8080/form_post {"message":"pingye","nick":"anonymous","status":"posted"}
Array type parameter
Sometimes (for example, check box) the front-end page will send the value of array type, which has the same name but different contents.
POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1 Content-Type: application/x-www-form-urlencoded
If it is still a QueryMap method, it is done. The method returns the map type by default.
router.GET("/post", func(c *gin.Context) { ids := c.QueryMap("ids") c.String(200, ids["a"]+" "+ids["b"]) })
curl http://localhost:8080/post?ids[a]=pingye&ids[b]=hehe pingye hehe
File upload
In general, file uploads will be directly transferred from the front end to cloud storage service providers, such as Alibaba cloud and qiniu cloud, etc., and less scenarios will be transferred to their own servers. In order to avoid the situation of less hate when books are used, let's have a look.
Gin provides the FormFile method to get the file stream. This method returns a variable of FileHeader type. You can call the Filename property to view the file name.
type FileHeader struct { Filename string Header textproto.MIMEHeader Size int64 content []byte tmpfile string }
router.POST("/upload", func(c *gin.Context) { file, _ := c.FormFile("file") c.String(200, file.Filename) })
Through the curl request interface, you can see that it is easy to get the file name.
curl -X POST http://localhost:8080/upload \ -F "file=@/Users/enoch/Downloads/IMG_9216.JPG" \ -H "Content-Type: multipart/form-data" IMG_9216.JPG
Of course, we can not only get the file name, but also use the SaveUploadedFile method to save the file to a certain place. When saving the file, we should ensure that we have the operation permission of the target directory.
router.POST("/upload", func(c *gin.Context) { file, _ := c.FormFile("file") c.String(200, file.Filename) err := c.SaveUploadedFile(file, "/Users/enoch/Desktop/ab.png") if err != nil { c.String(500, err.Error()) } })
Routing packet
When there are major changes to the interface (such as input and output parameters), considering the downward compatibility, an interface will be added generally. However, it is hoped that the name of the new interface is obviously the upgraded version of the old interface, so the version number v1/article can be added in front of the interface name.
v1 := r.Group("v1") { v1.POST("/login", func(c *gin.Context) { c.String(200, "v1/login") }) v1.POST("/submit", func(c *gin.Context) { c.String(200, "v1/submit") }) } v2 := r.Group("v2") { v2.POST("/login", func(c *gin.Context) { c.String(200, "v2/login") }) v2.POST("/submit", func(c *gin.Context) { c.String(200, "v2/submit") }) }
curl -X POST http://localhost:8080/v1/login curl -X POST http://localhost:8080/v2/login
Go language library code example, welcome star https://github.com/pingyeaa/golang-examples
Thank you for watching. If you think the article is helpful, please pay attention to the official account of "Ping Yi" and focus on the principle of Go language and technology.