3

我使用 golang 在我的应用程序中有多个结构。结构中的某些字段具有maxsize标签,有些则没有。例如:

type structone struct {
  fieldone string `valid:MaxSize(2)`
  fieldtwo string 
}

type structtwo struct {
  fieldone string `valid:MaxSize(2)`
  fieldtwo string 
}

所以我想为所有字段设置默认的最大大小,如果在运行时不包含任何有效的最大大小标签。可能吗?有人可以帮忙吗。

4

5 回答 5

3

我可以为结构中的字符串字段设置默认最大长度吗?

不。

于 2019-11-22T07:35:12.653 回答
2

预先声明的string类型不允许您限制string它可能持有的值的长度。

你可以做的是使用一个未导出的字段,这样它就不能在你的包之外被访问(设置),并提供一个设置方法来检查长度,如果它不符合你的要求则拒绝设置它(或限制值到允许的最大值)。

例如:

func (s *structone) SetFieldone(v string) error {
    if len(v) > 2 {
        return errors.New("too long")
    }
    s.fieldone = v
    return nil
}
于 2019-11-22T07:41:42.673 回答
0

该程序读取自身,将标签添加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
    }
}
于 2019-11-22T09:57:48.110 回答
0

其他答案似乎假设您在 Go 中使用香草字符串并询问您是否可以限制它们的最大大小。这可以通过提出的一些建议来实现。

但是,从您提供的代码片段中,我推断您在询问validate go 包是否可以使用标签指定结构中所有字段的默认最大大小。

不幸的是,该库目前不支持为所有字段指定默认验证标签。您必须为结构的所有字段显式定义验证标记。

但是,您尝试实现的目标是可能的,但是需要扩展库。

一个建议是扩展它以支持语法,例如:

type MyStruct struct {
    valid.Default `valid:MaxSize(5)`

    field1 string
    field2 string
}
于 2019-11-22T07:49:18.247 回答
-1

使用反射,不得不调整你的代码(错误的标签语法,私有道具)

package main

import (
    "fmt"
    "reflect"
)

func main() {

    a := structone{Fieldone: " eeeeeeee"}
    b := structtwo{Fieldtwo: " eeeeeeee"}
    maxLen(&a, 2)
    maxLen(&b, 4)
    fmt.Println(a)
    fmt.Println(b)
}

func maxLen(dst interface{}, max int) {

    prv := reflect.ValueOf(dst)

    if prv.Kind() != reflect.Ptr {
        return
    }

    rv := prv.Elem()

    if rv.Kind() != reflect.Struct {
        return
    }

    for i := 0; i < rv.NumField(); i++ {
        f := rv.FieldByIndex([]int{i})
        if f.CanInterface() {
            v := f.Interface()
            if s, ok := v.(string); ok {
                if len(s) > max {
                    s = s[:max]
                }
                f.Set(reflect.ValueOf(s))
            }
        }
    }
    return
}

type structone struct {
    Fieldone string
    Fieldtwo string
}

type structtwo struct {
    Fieldone string
    Fieldtwo string
}
于 2019-11-22T07:57:11.313 回答