Can I set default max length for string fields in struct?

7.4k views Asked by At

I have multiple structs in my application using golang. Some fields in a struct have maxsize tags, some does not have. for e.g:

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

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

So I want to set default maxsize for all fields, if does not contain any valid max size tags in run time. Is it possible? Can somebody help.

4

There are 4 answers

0
Volker On

Can I set default max length for string fields in struct?

No.

2
icza On

The string predeclared type does not allow you to limit the length of the string value it may hold.

What you may do is use an unexported field so it cannot be accessed (set) outside of your package, and provide a setter method in which you check the length, and refuse to set it if it does not meet your requirements (or cap the value to the allowed max).

For example:

func (s *structone) SetFieldone(v string) error {
    if len(v) > 2 {
        return errors.New("too long")
    }
    s.fieldone = v
    return nil
}
3
Preslav Mihaylov On

The other answers seem to assume you are using vanilla strings in Go and asking if you could limit their max size. That could be achieved with some of the suggestions made.

However, from the code snippet you have provided, I infer that you are asking whether the validate go package can specify a default max size of all fields in a struct using tags.

Unfortunately, that library does not currently support specifying a default validation tag for all fields. You have to explicitly define the validation tag for all fields of a struct.

What you are trying to achieve is possible, however, but the library needs to be extended.

One suggestion is extending it to support syntax such as:

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

    field1 string
    field2 string
}
0
AudioBubble On

this program read itself, add the tag valid:MaxSize(2) to the property structone.fieldone, then prints the updated program to 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
    }
}