golang 每日一庫之參數校驗工具 go-tagexpr

go-tagexpr 是字節跳動開源的一款輕量級 Go 標籤解析與表達式求值引擎。

我一般用來校驗參數。

它的主要功能是支持通過結構體標籤(struct tag)定義表達式,然後在運行時動態解析這些表達式,實現靈活的數據校驗、默認值設置等功能。

核心特性

VzBq9U

示例

type User struct {
    Name string `json:"name" tagexpr:"len(name) > 0"`
    Age  int    `json:"age"  tagexpr:"age >= 18"`
}
u := User{Name: "", Age: 17}
expr := tagexpr.New("tagexpr")
err := expr.Validate(&u)

上例中,Name 不能爲空字符串,Age 必須大於等於 18。Validate 方法會自動解析 tagexpr 標籤中的表達式,並在不滿足條件時返回錯誤。

示例 2

package tagexpr_test
import (
"fmt"
	tagexpr "github.com/bytedance/go-tagexpr/v2"
)
func Example() {
type T struct {
		A  int             `tagexpr:"$<0||$>=100"`
		B  string          `tagexpr:"len($)>1 && regexp('^\\w*$')"`
		C  bool            `tagexpr:"expr1:(f.g)$>0 && $; expr2:'C must be true when T.f.g>0'"`
		d  []string        `tagexpr:"@:len($)>0 && $[0]=='D'; msg:sprintf('invalid d: %v',$)"`
		e  map[string]int  `tagexpr:"len($)==$['len']"`
		e2 map[string]*int `tagexpr:"len($)==$['len']"`
		f  struct {
			g int `tagexpr:"$"`
		}
		h  int 				`tagexpr:"$>minVal"`
	}
	vm := tagexpr.New("tagexpr")
	t := &T{
		A:  107,
		B:  "abc",
		C:  true,
		d:  []string{"x", "y"},
		e:  map[string]int{"len": 1},
		e2: map[string]*int{"len": new(int)},
		f: struct {
			g int `tagexpr:"$"`
		}{1},
		h: 10,
	}
	tagExpr, err := vm.Run(t)
if err != nil {
panic(err)
	}
	fmt.Println(tagExpr.Eval("A"))
	fmt.Println(tagExpr.Eval("B"))
	fmt.Println(tagExpr.Eval("C@expr1"))
	fmt.Println(tagExpr.Eval("C@expr2"))
if !tagExpr.Eval("d").(bool) {
		fmt.Println(tagExpr.Eval("d@msg"))
	}
	fmt.Println(tagExpr.Eval("e"))
	fmt.Println(tagExpr.Eval("e2"))
	fmt.Println(tagExpr.Eval("f.g"))
	fmt.Println(tagExpr.EvalWithEnv("h", map[string]interface{}{"minVal": 9}))
	fmt.Println(tagExpr.EvalWithEnv("h", map[string]interface{}{"minVal": 11}))
// Output:
// true
// true
// true
// C must be true when T.f.g>0
// invalid d: [x y]
// true
// false
// 1
// true
// false
}

在 gin 中使用

import (
"github.com/bytedance/go-tagexpr/v2"
"github.com/gin-gonic/gin"
"net/http"
)
var expr = tagexpr.New("tagexpr")
func RegisterHandler(c *gin.Context) {
var req RegisterReq
if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "請求參數不合法"})
return
	}
if err := expr.Validate(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
	}
	c.JSON(http.StatusOK, gin.H{"message": "註冊成功"})
}

支持的表達式

支持對結構體字段進行調用與組合邏輯判斷,功能接近模板語言的表達式系統。

應用場景

性能如何

go-tagexpr 在表達式編譯時採用緩存機制,避免重複解析,提高了執行效率,

官方 benchmark 中表現良好,特別適合高併發業務校驗場景。

標題:golang 每日一庫之 go-tagexpr
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/06/26/1750915451642.html
聯繫:scotttu@163.com

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Hhm3VIo20c2Z_zE856o_Aw