我的应用程序中有多个使用 golang 的结构。结构体中的某些字段具有 maxsize 标签,有些则没有。 例如:
type structone struct {
fieldone string `valid:MaxSize(2)`
fieldtwo string
}
type structtwo struct {
fieldone string `valid:MaxSize(2)`
fieldtwo string
}
所以我想为所有字段设置默认的最大大小,如果在运行时不包含任何有效的最大大小标签。是否可以?有人可以帮忙吗。
我可以为结构体中的字符串字段设置默认最大长度吗?
没有。
string
预声明类型不允许您限制它可能保存的string
值的长度。
你可以做的是使用一个未导出的字段,这样它就不能在你的包之外被访问(设置),并提供一个setter方法来检查长度,如果它不符合你的要求(或上限),则拒绝设置它值到允许的最大值)。
例如:
func (s *structone) SetFieldone(v string) error {
if len(v) > 2 {
return errors.New("too long")
}
s.fieldone = v
return nil
}
其他答案似乎假设您在 Go 中使用普通字符串并询问您是否可以限制它们的最大大小。通过提出的一些建议可以实现这一目标。
但是,从您提供的代码片段中,我推断您是在询问 validate go package 是否可以使用标签指定结构中所有字段的默认最大大小。
不幸的是,该库当前不支持为所有字段指定默认验证标签。您必须为结构体的所有字段显式定义验证标记。
您想要实现的目标是可能的,但是库需要扩展。
一个建议是将其扩展以支持语法,例如:
type MyStruct struct {
valid.Default `valid:MaxSize(5)`
field1 string
field2 string
}
该程序读取自身,将标签
valid:MaxSize(2)
添加到属性structone.fieldone
,然后将更新的程序打印到os.Stdout
。
package main
import (
"go/ast"
"go/printer"
"go/token"
"log"
"os"
"strings"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/loader"
)
type structone struct {
fieldone string
fieldtwo string
}
func main() {
var conf loader.Config
_, err := conf.FromArgs([]string{"."}, false)
if err != nil {
log.Fatal(err)
}
prog, err := conf.Load()
if err != nil {
log.Fatal(err)
}
astutil.Apply(prog.InitialPackages()[0].Files[0], addTag("structone.fieldone", "`valid:MaxSize(2)`"), nil)
printer.Fprint(os.Stdout, prog.Fset, prog.InitialPackages()[0].Files[0])
}
func addTag(p string, tag string) func(*astutil.Cursor) bool {
pp := strings.Split(p, ".")
sName := pp[0]
pName := pp[1]
return func(cursor *astutil.Cursor) bool {
n := cursor.Node()
if x, ok := n.(*ast.TypeSpec); ok {
return x.Name.Name == sName
} else if x, ok := n.(*ast.Field); ok {
for _, v := range x.Names {
if v.Name == pName {
x.Tag = &ast.BasicLit{
Value: tag,
Kind: token.STRING,
}
}
}
} else if _, ok := n.(*ast.File); ok {
return true
} else if _, ok := n.(*ast.GenDecl); ok {
return true
} else if _, ok := n.(*ast.TypeSpec); ok {
return true
} else if _, ok := n.(*ast.StructType); ok {
return true
} else if _, ok := n.(*ast.FieldList); ok {
return true
}
return false
}
}
这个问题有点老了,但我相信帮助处于同样情况的其他人是值得的。 正如前面的答案之一所示,您将需要“验证器”包并对结构进行一些调整才能实现这一目标。
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type Structone struct {
Fieldone string `validate:"required,lt=10"`
Fieldtwo string `validate:"required,gte=8"`
}
var validate *validator.Validate
func main() {
s1 := &Structone{
Fieldone: "ok string",
Fieldtwo: "Error!",
}
validate = validator.New()
err := validate.Struct(s1)
if err != nil {
// get all error at once
errs := err.(validator.ValidationErrors)
fmt.Println(errs)
}
}