GitHub - bytedance/go-tagexpr: An interesting go struct tag expression syntax fo...
source link: https://github.com/bytedance/go-tagexpr
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
README.md
go-tagexpr
An interesting go struct tag expression syntax for field validation, etc.
Usage
Validator: A powerful validator that supports struct tag expression
Example
package tagexpr_test import ( "fmt" tagexpr "github.com/bytedance/go-tagexpr" ) 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:"$"` } } vm := tagexpr.New("tagexpr") err := vm.WarmUp(new(T)) if err != nil { panic(err) } 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}, } 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@")) // Output: // true // true // true // C must be true when T.f.g>0 // Invalid d: [x y] // true // false // 1 }
Syntax
Struct tag syntax spec:
type T struct {
// Single model
Field1 T1 `tagName:"expression"`
// Multiple model
Field2 T2 `tagName:"{exprName:expression} [{exprName2:expression2}]..."`
...
}
NOTE: The exprName
under the same struct field cannot be the same!
true
bool "true"
false
bool "false"
1
float64 "1"
1.0
float64 "1.0"
'S'
String "S"
+
Digital addition or string splicing
-
Digital subtraction or negative
*
Digital multiplication
/
Digital division
%
division remainder, as: float64(int64(a)%int64(b))
==
eq
!=
ne
>
gt
>=
ge
<
lt
<=
le
&&
Logic and
||
Logic or
()
Expression group
(X)$
Struct field value named X
(X.Y)$
Struct field value named X.Y
$
Shorthand for (X)$
, omit (X)
to indicate current struct field value
(X)$['A']
Map value with key A in the struct field X
(X)$[0]
The 0th element of the struct field X(type: map, slice, array)
len((X)$)
Built-in function len
, the length of struct field X
len()
Built-in function len
, the length of the current struct field
regexp('^\\w*$', (X)$)
Regular match the struct field X, return boolean
regexp('^\\w*$')
Regular match the current struct field, return boolean
sprintf('X value: %v', (X)$)
fmt.Sprintf
, format the value of struct field X
Operator priority(high -> low):
()
bool
string
float64
!
*
/
%
+
-
<
<=
>
>=
==
!=
&&
||
Selector
If expession is multiple model and exprName is not @
:
field_lv1.field_lv2...field_lvn@exprName
If expession is single model or exprName is @
:
field_lv1.field_lv2...field_lvn@
Benchmark
goos: darwin
goarch: amd64
pkg: github.com/bytedance/go-tagexpr
BenchmarkTagExpr-4 10000000 195 ns/op 40 B/op 4 allocs/op
BenchmarkReflect-4 10000000 208 ns/op 16 B/op 2 allocs/op
PASS
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK