One: request and request binding
1.1: Path parameters
: Parameter name, means to take the middle part.
*Parameter name, means all the data after fetching.
Path parameters, obtained with context.Param().
case:
package animal
import "github.com/gin-gonic/gin"
func Routers ( e * gin. Engine) {
e. GET ( "/animal/:name/*action" , testArgs)
}
package animal
import (
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
func testArgs ( context * gin. Context) {
name := context. Param ( "name" )
action := context. Param ( "action" )
action = strings. Split ( action, "/" ) [ 2 ]
context. String ( http. StatusOK, "name is %s, action is %s" , name, action)
}
1.2: Query String Parameters
DefaultQuery() returns the default value if the parameter does not exist, and returns an empty string if Query() does not exist.
DefaultQuery() case:
package animal
import "github.com/gin-gonic/gin"
func Routers ( e * gin. Engine) {
e. GET ( "/animal/login" , testArgs)
}
package animal
import (
"github.com/gin-gonic/gin"
"net/http"
)
func testArgs ( context * gin. Context) {
name := context. DefaultQuery ( "name" , "root" )
password := context. DefaultQuery ( "password" , "123456" )
context. String ( http. StatusOK, "name is %s, password is %s。" , name, password)
}
package animal
import (
"github.com/gin-gonic/gin"
"net/http"
)
func testArgs ( context * gin. Context) {
name := context. Query ( "name" )
password := context. Query ( "password" )
if name == "" || password == "" {
context. String ( http. StatusOK, "必要参数缺失" )
} else {
context. String ( http. StatusOK, "name is %s, password is %s。" , name, password)
}
}
1.3: Form parameters
PostForm() can parse form parameters
func testArgs ( context * gin. Context) {
name := context. PostForm ( "name" )
password := context. PostForm ( "password" )
if name == "" || password == "" {
context. String ( http. StatusOK, "必要参数缺失" )
} else {
context. String ( http. StatusOK, "name is %s, password is %s。" , name, password)
}
}
package animal
import (
"github.com/gin-gonic/gin"
"net/http"
)
func testArgs ( context * gin. Context) {
file, err := context. FormFile ( "file" )
if err != nil {
context. String ( 500 , "file upload fail, err msg is %s" , err)
return
}
err = context. SaveUploadedFile ( file, file. Filename)
if err != nil {
context. String ( 500 , "file save fail, err msg is %s" , err)
return
}
context. String ( http. StatusOK, file. Filename)
}
1.4: JSON data
The parameters are bound to the structure: context.ShouldBindJSON()
Note: First, you need to instantiate a structure object, and then pass in the reference of the structure object.
Why must the address be passed?
Because instantiated objects must be modified. If the essence of passing an object is to copy a new one, it will not change the current object.
package animal
import (
"github.com/gin-gonic/gin"
"net/http"
)
type LoginJsonArgs struct {
Name string `json:"name" binding:"required"`
Password string `json:"password" binding:"required"`
}
func testArgs ( context * gin. Context) {
var loginArgs LoginJsonArgs
err := context. ShouldBindJSON ( & loginArgs)
if err != nil {
context. JSON ( http. StatusBadRequest, gin. H{
"error" : err. Error ( ) } )
return
}
if loginArgs. Name != "root" && loginArgs. Password != "123456" {
context. JSON ( http. StatusUnauthorized, gin. H{
"status" : "401" , "msg" : "args validated fail" } )
} else {
context. JSON ( http. StatusOK, gin. H{
"status" : "200" , "msg" : "login success" } )
}
}
1.5: Forms can also bind structures
Restrict form binding in structure
type LoginJsonArgs struct {
Name string `form:"name" binding:"required"`
Password string `form:"password" binding:"required"`
}
The bound function uses Bind()
var loginArgs LoginJsonArgs
err := context. Bind ( & loginArgs)
if err != nil {
context. JSON ( http. StatusBadRequest, gin. H{
"error" : err. Error ( ) } )
return
}
1.6: Path parameter binding
type LoginJsonArgs struct {
Name string `uri:"name" binding:"required"`
Password string `uri:"password" binding:"required"`
}
The bind function takes ShouldBindUri()
var loginArgs LoginJsonArgs
err := context. ShouldBindUri ( & loginArgs)
if err != nil {
context. JSON ( http. StatusBadRequest, gin. H{
"error" : err. Error ( ) } )
return
}
import "github.com/gin-gonic/gin"
func Routers ( e * gin. Engine) {
e. GET ( "/animal/login/:name/:password" , testArgs)
}
1.7: Query string binding
The structure restricts the binding parameters: the same as the Form form.
type LoginJsonArgs struct {
Name string `form:"name" binding:"required"`
Password string `form:"password" binding:"required"`
}
Modify the binding method
var loginArgs LoginJsonArgs
err := context. ShouldBindQuery ( & loginArgs)
if err != nil {
context. JSON ( http. StatusBadRequest, gin. H{
"error" : err. Error ( ) } )
return
}
1.8: Binding Header
Structure limit request header parameters
type LoginJsonArgs struct {
Name string `header:"name" binding:"required"`
Password string `header:"password" binding:"required"`
}
Modify binding parameters
var loginArgs LoginJsonArgs
err := context. ShouldBindHeader ( & loginArgs)
if err != nil {
context. JSON ( http. StatusBadRequest, gin. H{
"error" : err. Error ( ) } )
return
}
1.9: Use the Bind or ShouldBind method?
Difference: If Bind fails to bind, it will automatically add 400 status code information to the response header.
It is recommended to use ShouldBind to let the front end judge based on the returned response information instead of using the status code of the response header.
Two: Response
2.1: Return JSON data
context. JSON ( http. StatusOK, gin. H{
"status" : "200" , "msg" : "login success" } )
2.2: return structure
The essence is to convert it into JSON and return it
package animal
import (
"github.com/gin-gonic/gin"
"net/http"
)
type LoginJsonArgs struct {
Name string `form:"name" binding:"required"`
Password string `form:"password" binding:"required"`
}
func testArgs ( context * gin. Context) {
var loginArgs LoginJsonArgs
err := context. ShouldBindQuery ( & loginArgs)
if err != nil {
context. JSON ( http. StatusBadRequest, gin. H{
"error" : err. Error ( ) } )
return
}
if loginArgs. Name != "root" && loginArgs. Password != "123456" {
context. JSON ( http. StatusUnauthorized, gin. H{
"status" : "401" , "msg" : "args validated fail" } )
} else {
context. JSON ( http. StatusOK, loginArgs)
}
}
2.3: Return to protobuf
reps := [ ] int64 {
int64 ( 1 ) , int64 ( 2 ) }
label := "resData"
resData := & protoexample. Test{
Label: & label,
Reps: reps,
}
context. ProtoBuf ( 200 , resData)
2.4: Return redirection
context. Redirect ( http. StatusMovedPermanently, "XXX地址" )
Three: asynchronous context
In an asynchronous request, if the context is to be used, the context must be copied again.
package main
import (
"log"
"time"
"github.com/gin-gonic/gin"
)
func main ( ) {
r := gin. Default ( )
r. GET ( "/long_async" , func ( c * gin. Context) {
copyContext := c. Copy ( )
go func ( ) {
time. Sleep ( 3 * time. Second)
log. Println ( "异步执行:" + copyContext. Request. URL. Path)
} ( )
} )
r. Run ( ":8000" )
}