最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang中web參數(shù)校驗(yàn)的實(shí)現(xiàn)

 更新時(shí)間:2025年11月02日 09:51:06   作者:Asakeiii  
本文介紹了使用Gin框架進(jìn)行參數(shù)校驗(yàn)的幾種方法,包括JSON、URL查詢、表單數(shù)據(jù)的校驗(yàn),常用校驗(yàn)規(guī)則,自定義錯(cuò)誤信息和自定義校驗(yàn)規(guī)則,具有一定的參考價(jià)值,感興趣的可以了解一下

參數(shù)校驗(yàn)

確保我們的應(yīng)用接收到的數(shù)據(jù)是格式正確并且安全的

基本用法

JSON

假設(shè)我們正在開(kāi)發(fā)一個(gè)登錄接口,希望用戶必須提供用戶名和密碼。在 Gin 中,我們首先會(huì)定義一個(gè) Go 的 struct 來(lái)描述這個(gè)數(shù)據(jù)結(jié)構(gòu)。

type Login struct {
	User     string `json:"user" binding:"required"`
	Password string `json:"password" binding:"required"`
}
  • json:“…” 標(biāo)簽: 這個(gè)標(biāo)簽告訴 Gin,當(dāng)它解析傳入的 JSON 數(shù)據(jù)時(shí),JSON 中的 user 字段應(yīng)該映射到我們結(jié)構(gòu)體中的 User 字段。
  • binding:“required” 標(biāo)簽: 這是最核心的部分!binding 就是用來(lái)做數(shù)據(jù)校驗(yàn)的。required 是一個(gè)校驗(yàn)規(guī)則,意思是“這個(gè)字段是必填的,不能為空”。
func loginHandler(c *gin.Context) {
	var login Login

	// 嘗試將請(qǐng)求的 JSON body 綁定到 login 結(jié)構(gòu)體上
	// 在綁定的同時(shí),Gin 會(huì)根據(jù) "binding" 標(biāo)簽進(jìn)行校驗(yàn)
	err := c.ShouldBindJSON(&login)
	if err != nil {
		// 如果 err 不是 nil,說(shuō)明校驗(yàn)失敗了!
		// 比如,某個(gè) "required" 的字段沒(méi)有被提供。
		// Gin 通常會(huì)自動(dòng)返回一個(gè) 400 Bad Request 錯(cuò)誤。
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 如果 err 是 nil,說(shuō)明所有校驗(yàn)都通過(guò)了!
	c.JSON(200, gin.H{"status": "you are logged in"})
}

URL

除了處理 JSON,我們經(jīng)常還需要處理來(lái)自 URL 查詢(Query)和 HTML 表單(Form)的數(shù)據(jù)。
Gin 的設(shè)計(jì)非常統(tǒng)一。我們的 struct 定義方式幾乎不變,只需要更換一個(gè)綁定方法就可以了。

如何校驗(yàn) URL 查詢參數(shù),比如這樣一個(gè)請(qǐng)求:GET /search?keyword=gin&page=1
我們希望 keyword 是必填的,并且 page 必須是一個(gè)大于 0 的數(shù)字。
首先,還是定義我們的 struct:

type SearchQuery struct {
	Keyword string `form:"keyword" binding:"required"`
	Page    int    `form:"page"    binding:"required,gt=0"`
}
  • 我們用了 form:“…” 標(biāo)簽,而不是 json:“…”。這個(gè) form 標(biāo)簽既可以用于 URL 查詢參數(shù),也可以用于表單數(shù)據(jù)。
  • 我在 Page 字段的 binding 里加了一個(gè)新規(guī)則 gt=0,它的意思是 “greater than 0(必須大于0)。
func searchHandler(c *gin.Context) {
    var query SearchQuery

    // 從 URL query 中綁定并校驗(yàn)參數(shù)
    // 注意這里換成了 ShouldBindQuery
    err := c.ShouldBindQuery(&query)

    if err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }

    // 校驗(yàn)通過(guò)!
    c.JSON(200, gin.H{
        "message": "search parameters are valid",
        "keyword": query.Keyword,
        "page":    query.Page,
    })
}

常用的校驗(yàn)規(guī)則

我們通過(guò)一個(gè)用戶注冊(cè)的例子來(lái)看看:

type RegisterUser struct {
	// 用戶名:必填,長(zhǎng)度在 4 到 20 個(gè)字符之間
	Username string `json:"username" binding:"required,min=4,max=20"`

	// 郵箱:必填,且必須是合法的郵箱格式
	Email string `json:"email" binding:"required,email"`

	// 年齡:選填,但如果提供了,必須大于等于 18 歲,小于等于 100 歲
	Age int `json:"age" binding:"gte=18,lte=100"`

	// 用戶類型:必填,并且值必須是 'user' 或 'admin' 中的一個(gè)
	UserType string `json:"user_type" binding:"required,oneof=user admin"`
}
  • min=4,max=20:用于字符串、數(shù)組等,限制其最小和最大長(zhǎng)度。多個(gè)規(guī)則用逗號(hào) , 分隔。
  • email:檢查字符串是否符合標(biāo)準(zhǔn)的 email 格式。
  • gte=18:意思是 “Greater Than or Equal To”,即大于或等于 18。
  • lte=100:意思是 “Less Than or Equal To”,即小于或等于 100。
  • oneof=user admin:表示這個(gè)字段的值必須是后面列出的值之一(用空格分隔)。
func registerUserHandler(c *gin.Context) {
	var register RegisterUser
	err := c.ShouldBindJSON(&register)
	if err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	c.JSON(200, gin.H{
		"username": register.Username,
		"email":    register.Email,
	})
}

自定義錯(cuò)誤信息

核心思路是:捕獲到校驗(yàn)錯(cuò)誤后,我們不再直接把它整個(gè)返回,而是逐一檢查是哪個(gè)字段的哪條規(guī)則出錯(cuò)了,然后根據(jù)這些信息,手動(dòng)“翻譯”成我們想展示的話。

func registerUserHandler(c *gin.Context) {
	var register RegisterUser
	err := c.ShouldBindJSON(&register)
	if err != nil {
		var verrs validator.ValidationErrors
		ok := errors.As(err, &verrs)
		if !ok {
			// 如果不是 ValidationErrors 類型的錯(cuò)誤,直接返回原始錯(cuò)誤
			c.JSON(400, gin.H{"error": err.Error()})
			return
		}
		// 創(chuàng)建一個(gè) map 來(lái)存放我們“翻譯”后的錯(cuò)誤信息
		// key 是字段名,value 是錯(cuò)誤信息
		// 比如:{"Username": "長(zhǎng)度不能小于 4 個(gè)字符"}
		translatedErrors := make(map[string]string)
		for _, fe := range verrs {
			// fe.Field() 獲取出錯(cuò)的字段名,比如 "Username"
			translatedErrors[fe.Field()] = getErrorMsg(fe)
		}

		c.JSON(400, gin.H{"errors": translatedErrors})
		return
	}

	c.JSON(200, gin.H{
		"username": register.Username,
		"email":    register.Email,
	})
}

// 這個(gè)函數(shù)專門(mén)用來(lái)“翻譯”錯(cuò)誤信息
func getErrorMsg(fe validator.FieldError) string {
	// fe.Tag() 能獲取到是哪個(gè)校驗(yàn)規(guī)則出錯(cuò)了,比如 "required", "min", "email"
	switch fe.Tag() {
	case "required":
		return "這是必填項(xiàng)"
	case "min":
		// fe.Param() 能獲取到規(guī)則后面的參數(shù),比如 "min=4" 中的 "4"
		return "長(zhǎng)度不能小于 " + fe.Param() + " 個(gè)字符"
	case "max":
		return "長(zhǎng)度不能超過(guò) " + fe.Param() + " 個(gè)字符"
	case "email":
		return "請(qǐng)輸入正確的郵箱地址"
	case "oneof":
		return "必須是 " + fe.Param() + " 中的一個(gè)"
	default:
		return "未知錯(cuò)誤"
	}
}

自定義校驗(yàn)規(guī)則

當(dāng)內(nèi)置的規(guī)則(像 required, email, min, max 等)不夠用時(shí),我們就需要自定義規(guī)則。比如,我們想強(qiáng)制要求“密碼必須同時(shí)包含字母和數(shù)字”。

整個(gè)過(guò)程分為三步,我們一步一步來(lái):

  1. 編寫(xiě)一個(gè)自定義校驗(yàn)函數(shù)
    這個(gè)函數(shù)需要一個(gè)特定的格式。它接收一個(gè) validator.FieldLevel 類型的參數(shù),并返回一個(gè) bool 值。返回 true 表示校驗(yàn)通過(guò),false 表示失敗。
// isPasswordStrong 就是我們的自定義校驗(yàn)函數(shù)
func isPasswordStrong(fl validator.FieldLevel) bool {
    // fl.Field().String() 可以獲取到字段的字符串值
    password := fl.Field().String()
    
    hasLetter := false
    hasDigit := false

    // 遍歷密碼字符串,檢查是否同時(shí)包含字母和數(shù)字
    for _, char := range password {
        if unicode.IsLetter(char) {
            hasLetter = true
        }
        if unicode.IsDigit(char) {
            hasDigit = true
        }
    }
    
    return hasLetter && hasDigit
}
  1. 將自定義函數(shù)“注冊(cè)”到 Gin 的校驗(yàn)器里
    光寫(xiě)好函數(shù)還不行,我們得告訴 Gin 的校驗(yàn)器:“嘿,我這里有一個(gè)新的校驗(yàn)規(guī)則,它的名字叫 strong_password,對(duì)應(yīng)的處理函數(shù)是 isPasswordStrong。”

    這個(gè)注冊(cè)過(guò)程通常在你的程序啟動(dòng)時(shí)(比如 main 函數(shù)里)完成。

// 從 Gin 的 binding 中獲取底層的 validator 引擎
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		// 注冊(cè)我們的自定義校驗(yàn)函數(shù)
		// 第一個(gè)參數(shù)是這個(gè)規(guī)則在 struct tag 中使用的名字
		// 第二個(gè)參數(shù)是我們的函數(shù)
		v.RegisterValidation("strong_password", isPasswordStrong)
	}
  1. 在 Struct Tag 中使用新規(guī)則
    一旦注冊(cè)成功,我們就可以像使用任何內(nèi)置規(guī)則一樣,在 struct tag 中使用 strong_password 了。

到此這篇關(guān)于Golang中web參數(shù)校驗(yàn)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Golang web參數(shù)校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入了解Golang?interface{}的底層原理實(shí)現(xiàn)

    深入了解Golang?interface{}的底層原理實(shí)現(xiàn)

    在?Go?語(yǔ)言沒(méi)有泛型之前,接口可以作為一種替代實(shí)現(xiàn),也就是萬(wàn)物皆為的?interface。那到底?interface?是怎么設(shè)計(jì)的底層結(jié)構(gòu)呢?下面咱們透過(guò)底層分別看一下這兩種類型的接口原理。感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助
    2022-10-10
  • Golang中Error的設(shè)計(jì)與實(shí)踐詳解

    Golang中Error的設(shè)計(jì)與實(shí)踐詳解

    這篇文章主要為大家詳細(xì)介紹了Golang中Error的設(shè)計(jì)以及是具體如何處理錯(cuò)誤的相關(guān)知識(shí),文中的示例代碼簡(jiǎn)潔易懂,需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-08-08
  • golang基礎(chǔ)之字符串與int、int64類型互相轉(zhuǎn)換

    golang基礎(chǔ)之字符串與int、int64類型互相轉(zhuǎn)換

    這篇文章主要給大家介紹了關(guān)于golang基礎(chǔ)之字符串與int、int64類型互相轉(zhuǎn)換的相關(guān)資料,在Go語(yǔ)言中string轉(zhuǎn)int是一項(xiàng)常見(jiàn)的操作,需要的朋友可以參考下
    2023-07-07
  • go env環(huán)境變量配置的使用

    go env環(huán)境變量配置的使用

    在安裝和使用Go時(shí),必須要正確地配置環(huán)境變量,本文主要介紹了go env環(huán)境變量配置的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • Go標(biāo)準(zhǔn)庫(kù)http?server的優(yōu)雅關(guān)閉深入理解

    Go標(biāo)準(zhǔn)庫(kù)http?server的優(yōu)雅關(guān)閉深入理解

    這篇文章主要為大家介紹了Go標(biāo)準(zhǔn)庫(kù)http?server的優(yōu)雅有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪關(guān)閉深入理解
    2024-01-01
  • Go 并發(fā)控制 errgroup.Group的實(shí)現(xiàn)示例

    Go 并發(fā)控制 errgroup.Group的實(shí)現(xiàn)示例

    本文主要介紹了Go 并發(fā)控制 errgroup.Group的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2026-04-04
  • 詳解minio分布式文件存儲(chǔ)

    詳解minio分布式文件存儲(chǔ)

    MinIO 是一款基于 Go 語(yǔ)言的高性能、可擴(kuò)展、云原生支持、操作簡(jiǎn)單、開(kāi)源的分布式對(duì)象存儲(chǔ)產(chǎn)品,這篇文章主要介紹了minio分布式文件存儲(chǔ),需要的朋友可以參考下
    2023-10-10
  • 使用Gin框架搭建一個(gè)Go Web應(yīng)用程序的方法詳解

    使用Gin框架搭建一個(gè)Go Web應(yīng)用程序的方法詳解

    在本文中,我們將要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Web 應(yīng)用程序,通過(guò) Gin 框架來(lái)搭建,主要支持用戶注冊(cè)和登錄,用戶可以通過(guò)注冊(cè)賬戶的方式創(chuàng)建自己的賬號(hào),并通過(guò)登錄功能進(jìn)行身份驗(yàn)證,感興趣的同學(xué)跟著小編一起來(lái)看看吧
    2023-08-08
  • Go 類型轉(zhuǎn)化工具庫(kù)cast函數(shù)詳解

    Go 類型轉(zhuǎn)化工具庫(kù)cast函數(shù)詳解

    這篇文章主要介紹了Go 類型轉(zhuǎn)化工具庫(kù)cast函數(shù)詳解,cast 是在Github上開(kāi)源的工具庫(kù),就像他的名字一樣,他為我們提供了非常便捷的類型轉(zhuǎn)化的方法
    2022-07-07
  • golang中select語(yǔ)句的簡(jiǎn)單實(shí)例

    golang中select語(yǔ)句的簡(jiǎn)單實(shí)例

    Go的select語(yǔ)句是一種僅能用于channl發(fā)送和接收消息的專用語(yǔ)句,此語(yǔ)句運(yùn)行期間是阻塞的,下面這篇文章主要給大家介紹了關(guān)于golang中select語(yǔ)句的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06

最新評(píng)論

广宁县| 海丰县| 沧源| 怀仁县| 石嘴山市| 五家渠市| 河北区| 江油市| 桓台县| 巴彦县| 新化县| 新民市| 乐陵市| 曲靖市| 青岛市| 军事| 忻城县| 无极县| 桐乡市| 丰顺县| 噶尔县| 惠安县| 长沙市| 玉林市| 禄丰县| 张家口市| 宁安市| 宝丰县| 新郑市| 临湘市| 台山市| 靖西县| 重庆市| 锡林浩特市| 略阳县| 屏东市| 鄂托克前旗| 汝阳县| 扎鲁特旗| 托克托县| 英超|