func (m *Example) Validate() error {
if m.GetInt64Const() != int64(123) {
return fmt.Errorf("field Int64Const not match const value, current value: %v", m.GetInt64Const())
}
if m.GetDoubleLe() > float64(123.45) {
return fmt.Errorf("field DoubleLe le rule failed, current value: %v", m.GetDoubleLe())
}
if m.GetBoolConst() != true {
return fmt.Errorf("field BoolConst const rule failed, current value: %v", m.GetBoolConst())
}
if len(m.GetStringMaxSize()) > int(12) {
return fmt.Errorf("field StringMaxSize max_len rule failed, current value: %d", len(m.GetStringMaxSize()))
}
_src := []byte("validator")
if !bytes.HasPrefix(m.GetBytesPrefix(), _src) {
return fmt.Errorf("field bytesPrefix prefix rule failed, current value: %v", m.GetBytesPrefix())
}
for i := 0; i < len(m.GetListElem()); i++ {
_elem := m.GetListElem()[i]
_src1 := "validator"
if _elem != _src1 {
return fmt.Errorf("field _elem not match const value, current value: %v", _elem)
}
}
for k := range m.GetMapKeyValue() {
if k != int32(123) {
return fmt.Errorf("field k not match const value, current value: %v", k)
}
if k <= int32(100) {
return fmt.Errorf("field k gt rule failed, current value: %v", k)
}
}
for _, v := range m.GetMapKeyValue() {
_src2 := "validator"
if v != _src2 {
return fmt.Errorf("field v not match const value, current value: %v", v)
}
_src3 := "validator"
if !strings.HasPrefix(v, _src3) {
return fmt.Errorf("field v prefix rule failed, current value: %v", v)
}
}
_src4 := m.GetInt64Const() + int64(1000)
if m.GetFunc1() <= int64(_src4) {
return fmt.Errorf("field Func1 gt rule failed, current value: %v", m.GetFunc1())
}
return nil
}
### 内置函数
`protoc-gen-validator` 提供一组内置函数以便编写校验规则
| function name | arguments | results | remarks |
| ------------- | ----------------------------------------------------- | ------------------------------------------------------ | --------------------------------------- |
| len | 1: container filed | 1: length of container (integer) | just like `len` of go |
| sprintf | 1: format string <br /> 2+: arguments matching format | 1: formatted string (string) | just like `fmt.Sprintf` of go |
| now_unix_nano | none | 1: nano seconds (int64) | just like `time.Now().UnixNano()` of go |
| equal | 1, 2: comparable values | 1: whether two arguments is equal (bool) | just like `==` of go |
| mod | 1, 2: integer | 1: remainder of $1 / $2 (integer) | just like `%` of go |
| add | 1, 2: both are numeric or string | 1: sum of two arguments (integer or float64 or string) | just like `+` of go |
### 自定义验证函数
`protoc-gen-validator` 提供拓展验证函数的方法
现在你可以使用参数 `func` 去自定义你的验证函数。如下:
`my_func` 是函数的名字, `path_to_template.txt` 是函数的模板文件,该模板应该是一个标准的 go 模板。
可用的模板变量如下:
| 变量名 | 含义 | 类型 |
| ------------- | ------------------------------------- | ---------------------------------------------------------------- |
| Source | variable name that rule will refer to | string |
| Function | data of current function | *"github.com/cloudwego/protoc-gen-validator/parser".ToolFunction |
protoc-gen-validator
protoc-gen-validator 是一个可以生成 go 结构体校验函数的 protoc 插件。
开发者可以引用 “protoc-gen-validator” 拓展的注解文件,并使用这些注解对 protobuf 的 message 和 field 的约束进行声明。 最后,”protoc-gen-validator” 会为对应的 message 生成
Validate() error方法。例:
生成的方法:
使用方法
依赖
$PATH下$PATH/$GOPATH下protoc-gen-validator位于$PATH/$GOPATH下proto2/proto3语法,更推荐使用proto3语法Installation
go install github.com/cloudwego/protoc-gen-validator@latestParameters
protoc-gen-validator版本Examples
校验函数(example_validate.pb.go)的生成位置与 protoc-gen-go 的一致。 ``` cd exampleprotoc
-I .
–go_out=.
–validator_out=.
example.proto
cd example
protoc
-I .
–go_out=.
–go_opt=source_relative
–validator_out=.
–validator_opt=source_relative
example.proto
// option go_package=”example.com/validator/example”; cd example
protoc
-I .
–go_out=.
–go_opt=module=example.com/validator
–validator_out=.
–validator_opt=module=example.com/validator
example.proto
// 不指定 go module hz new -I={INCLUDEPATH} \ -idl={IDLPATH}
-protoc-plugins=validator:hz=true:. // 指定 go module hz new -I={INCLUDEPATH} \ -idl={IDLPATH}
-protoc-plugins=validator:hz=true,go_mod={GOMODULE}:. -mod={GOMODULE}
// option go_package={GOMODULE}/{MODELDIR}/x/y/z // 其中 {MODELDIR} 默认为 "biz/model" hz new -I={INCLUDEPATH} \ -idl={IDLPATH} \ -protoc-plugins=validator:module={GOMODULE},recurse=true:. \ -mod={$GOMODULE}
int32 Int32Const = 1 [(api.vt).const=”123”];
optional double DoubleLe = 2 [(api.vt).le=”123.54”];
// 由于 ‘in’ 约束是一个列表,所以这里的写法稍有不同 optional fixed32 Fix32In = 3 [(api.vt)={in: [“123”,”456”,”789”]}];
optional int64 I64NotNil = 4 [(api.vt).not_nil=”true”];
optional bool BoolConst = 1 [(api.vt).const=”true”];
optional bool BoolNotNil = 2 [(api.vt).not_nil=”true”];
optional string StringConst = 1 [(api.vt).const=”validator”]; optional bytes bytesConst = 2 [(api.vt).const=”validator”];
optional string StringPattern = 3 [(api.vt).pattern=”[0-9A-Za-z]+”]; optional bytes bytesPattern = 4 [(api.vt).pattern=”[0-9A-Za-z]+”];
optional string StringMinSize = 5 [(api.vt).min_size=”12”]; optional bytes bytesMaxSize = 6 [(api.vt).max_size=”12”];
optional string StringPrefix = 7 [(api.vt).prefix=”validator”]; optional string StringSuffix = 8 [(api.vt).suffix=”validator”]; optional bytes bytesContain = 9 [(api.vt).contains=”validator”]; optional bytes bytesNotContain = 10 [(api.vt).not_contains=”validator”];
// 由于 ‘in’ 约束是一个列表,所以这里的写法稍有不同 optional string StringIn = 11 [(api.vt)={in:[“123”,”456”,”789”]}]; optional bytes bytesNotIn = 12 [(api.vt)={not_in:[“123”,”456”,”789”]}];
optional string StringNotNil = 13 [(api.vt).not_nil=”true”];
enum EnumType { TWEET = 0; RETWEET = 1; }
optional EnumType Enum1 = 1 [(api.vt).const=”EnumType.TWEET”];
optional EnumType Enum2 = 2 [(api.vt).defined_only=”true”];
optional EnumType Enum3 = 3 [(api.vt).not_nil=”true”];
repeated string ListMinSize = 1 [(api.vt).min_size=”12”];
repeated string ListBaseElem = 2 [(api.vt).elem.const=”validator”];
map<int32, string> MapISMinSize = 1 [(api.vt).min_size=”10”, (api.vt).max_size=”30”];
map<int32, string> MapKey = 2 [(api.vt).key.const=”123”, (api.vt).key.gt=”12”];
map<int32, string> MapValue = 3 [(api.vt).value.const=”validator”, (api.vt).value.prefix=”validator”];
map<int32, MsgType> MapNoSparse = 4 [(api.vt).no_sparse=”true”];
optional MapValidate MsgField = 1 [(api.vt).skip=”true”];
message StructValidate { option (api.msg_vt).assert = “@equal($MsgValidate,1)”; optional int64 MsgValidate = 1; }
optional double DoubleLe = 1; optional double Reference = 2 [(api.vt).le=”$DoubleLe”];
cd example
protoc
-I .
–go_out=.
–validator_out=.
–validator_opt=func=my_func=path_to_template.txt
example.proto