02-Gin リクエストパラメータ

1: リクエストとリクエストバインディング

1.1: パスパラメータ

  • : パラメータ名。中間部分を取ることを意味します。
  • ※パラメータ名とは、取得後の全データを指します。
  • パスパラメータ。 context.Param() で取得します。
  • 場合:
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) {
    
    
	// 请求:http://127.0.0.1:8080/animal/dog/jiao/wangwang
	name := context.Param("name")          // dog
	action := context.Param("action")      // /jiao/wangwang
	action = strings.Split(action, "/")[2] // wangwang
	context.String(http.StatusOK, "name is %s, action is %s", name, action)
}

1.2: クエリ文字列パラメータ

  • DefaultQuery() は、パラメータが存在しない場合はデフォルト値を返し、Query() が存在しない場合は空の文字列を返します。
  • DefaultQuery() の場合:
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) {
    
    
	// 请求: http://127.0.0.1:8080/animal/login?name=dog&password=1234567890
	name := context.DefaultQuery("name", "root")
	password := context.DefaultQuery("password", "123456")
	context.String(http.StatusOK, "name is %s, password is %s。", name, password)
}
  • Query()の場合
package animal

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func testArgs(context *gin.Context) {
    
    
	// 请求: http://127.0.0.1:8080/animal/login?name=dog&password=1234567890
	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: フォームパラメータ

  • PostForm() はフォームパラメータを解析できます
func testArgs(context *gin.Context) {
    
    
	// 请求:multipart/form-data
	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) {
    
    
	// 请求:multipart/form-data
	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データ

  • パラメータは構造体 context.ShouldBindJSON() にバインドされます。
  • 注: まず、構造体オブジェクトをインスタンス化してから、構造体オブジェクトの参照を渡す必要があります。
  • なぜアドレスを渡す必要があるのでしょうか?
    • インスタンス化されたオブジェクトは変更する必要があるためです。オブジェクトを渡すことの本質が新しいオブジェクトをコピーすることである場合、現在のオブジェクトは変更されません。
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) {
    
    
	// 请求:JSON数据
	// 获取JSON参数并绑定参数
	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: フォームは構造をバインドすることもできます

  • 構造内のフォームバインディングを制限する
type LoginJsonArgs struct {
    
    
	Name     string `form:"name" binding:"required"`
	Password string `form:"password" binding:"required"`
}
  • バインドされた関数は Bind() を使用します
	var loginArgs LoginJsonArgs
	err := context.Bind(&loginArgs)
	if err != nil {
    
    
		context.JSON(http.StatusBadRequest, gin.H{
    
    "error": err.Error()})
		return
	}

1.6: パスパラメータのバインディング

  • 構造体の制限バインディング
type LoginJsonArgs struct {
    
    
	Name     string `uri:"name" binding:"required"`
	Password string `uri:"password" binding:"required"`
}
  • バインド関数は 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: クエリ文字列バインディング

  • この構造はバインディング パラメータを制限します。これは Form フォームと同じです。
type LoginJsonArgs struct {
    
    
	Name     string `form:"name" binding:"required"`
	Password string `form:"password" binding:"required"`
}
  • バインディング方法を変更する
	var loginArgs LoginJsonArgs
	err := context.ShouldBindQuery(&loginArgs)
	if err != nil {
    
    
		context.JSON(http.StatusBadRequest, gin.H{
    
    "error": err.Error()})
		return
	}

1.8: バインディングヘッダー

  • 構造制限リクエストヘッダーパラメータ
type LoginJsonArgs struct {
    
    
	Name     string `header:"name" binding:"required"`
	Password string `header:"password" binding:"required"`
}
  • バインドパラメータを変更する
	var loginArgs LoginJsonArgs
	err := context.ShouldBindHeader(&loginArgs)
	if err != nil {
    
    
		context.JSON(http.StatusBadRequest, gin.H{
    
    "error": err.Error()})
		return
	}

1.9: Bind メソッドまたは ShouldBind メソッドを使用しますか?

  • 違い: Bind がバインドに失敗した場合、応答ヘッダーに 400 ステータス コード情報が自動的に追加されます。
  • レスポンスヘッダーのステータスコードではなく、ShouldBindを使用して、返されたレスポンス情報をもとにフロントエンドに判断させることを推奨します。

2: 応答

2.1: JSON データを返す

context.JSON(http.StatusOK, gin.H{
    
    "status": "200", "msg": "login success"})

2.2: 戻り構造

  • 本質はJSONに変換して返すことです
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) {
    
    
	// 绑定Header
	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: protobuf に戻る

		// 自定义PB格式
		reps := []int64{
    
    int64(1), int64(2)}
		label := "resData"
		resData := &protoexample.Test{
    
    
			Label: &label,
			Reps:  reps,
		}
		context.ProtoBuf(200, resData)

2.4: リターンリダイレクト

 context.Redirect(http.StatusMovedPermanently, "XXX地址")

3: 非同期コンテキスト

  • 非同期リクエストでコンテキストを使用する場合は、コンテキストを再度コピーする必要があります。
package main

import (
    "log"
    "time"

    "github.com/gin-gonic/gin"
)

func main() {
    
    
    r := gin.Default()
    // 1.异步
    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")
}

おすすめ

転載: blog.csdn.net/qq_41341757/article/details/126768569