Iterate Over String Fields in Struct

后端 未结 3 546
夕颜
夕颜 2020-12-28 11:58

I\'m looking to iterate over the string fields of a struct so I can do some clean-up/validation (with strings.TrimSpace, strings.Trim, etc).

<
3条回答
  •  醉梦人生
    2020-12-28 12:22

    What you want is primarily the methods on reflect.Value called NumFields() int and Field(int). The only thing you're really missing is the string check and SetString method.

    package main
    
    import "fmt"
    import "reflect"
    import "strings"
    
    type MyStruct struct {
        A,B,C string
        I int
        D string
        J int
    }
    
    func main() {
        ms := MyStruct{"Green ", " Eggs", " and ", 2, " Ham      ", 15}
        // Print it out now so we can see the difference
        fmt.Printf("%s%s%s%d%s%d\n", ms.A, ms.B, ms.C, ms.I, ms.D, ms.J)
    
        // We need a pointer so that we can set the value via reflection
        msValuePtr := reflect.ValueOf(&ms)
        msValue := msValuePtr.Elem()
    
        for i := 0; i < msValue.NumField(); i++ {
            field := msValue.Field(i)
    
            // Ignore fields that don't have the same type as a string
            if field.Type() != reflect.TypeOf("") {
                continue
            }
    
            str := field.Interface().(string)
            str = strings.TrimSpace(str)
            field.SetString(str)
        }
        fmt.Printf("%s%s%s%d%s%d\n", ms.A, ms.B, ms.C, ms.I, ms.D, ms.J)
    }
    

    (Playground link)

    There are two caveats here:

    1. You need a pointer to what you're going to change. If you have a value, you'll need to return the modified result.

    2. Attempts to modify unexported fields generally will cause reflect to panic. If you plan on modifying unexported fields, make sure to do this trick inside the package.

    This code is rather flexible, you can use switch statements or type switches (on the value returned by field.Interface()) if you need differing behavior depending on the type.

    Edit: As for the tag behavior, you seem to already have that figured out. Once you have field and have checked that it's a string, you can just use field.Tag.Get("max") and parse it from there.

    Edit2: I made a small error on the tag. Tags are part of the reflect.Type of a struct, so to get them you can use (this is a bit long-winded) msValue.Type().Field(i).Tag.Get("max")

    (Playground version of the code you posted in the comments with a working Tag get).

提交回复
热议问题