Iterate Over String Fields in Struct

后端 未结 3 556
夕颜
夕颜 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:10

    I got beat to the punch, but since I went to the work, here's a solution:

    type FormError []*string
    
    type Listing struct {
        Title        string `max:"50"`
        Location     string `max:"100"`
        Description  string `max:"10000"`
        ExpiryDate   time.Time
        RenderedDesc template.HTML
        Contact      string `max:"255"`
    }
    
    // Iterate over our struct, fix whitespace/formatting where possible
    // and return errors encountered
    func (l *Listing) Validate() error {
        listingType := reflect.TypeOf(*l)
        listingValue := reflect.ValueOf(l)
        listingElem := listingValue.Elem()
    
        var invalid FormError = []*string{}
        // Iterate over fields
        for i := 0; i < listingElem.NumField(); i++ {
            fieldValue := listingElem.Field(i)
            // For StructFields of type string, field = strings.TrimSpace(field)
            if fieldValue.Type().Name() == "string" {
                newFieldValue := strings.TrimSpace(fieldValue.Interface().(string))
                fieldValue.SetString(newFieldValue)
    
                fieldType := listingType.Field(i)
                maxLengthStr := fieldType.Tag.Get("max")
                if maxLengthStr != "" {
                    maxLength, err := strconv.Atoi(maxLengthStr)
                    if err != nil {
                        panic("Field 'max' must be an integer")
                    }
                    //     check max length/convert to int/utf8.RuneCountInString
                    if utf8.RuneCountInString(newFieldValue) > maxLength {
                        //     if max length exceeded, invalid = append(invalid, "errormsg")
                        invalidMessage := `"`+fieldType.Name+`" is too long (max allowed: `+maxLengthStr+`)`
                        invalid = append(invalid, &invalidMessage)
                    }
                }
            }
        }
    
        if len(invalid) > 0 {
            return invalid
        }
    
        return nil
    }
    
    func (f FormError) Error() string {
        var fullError string
        for _, v := range f {
            fullError = *v + "\n"
        }
        return "Errors were encountered during form processing: " + fullError
    }
    

    I see you asked about how to do the tags. Reflection has two components: a type and a value. The tag is associated with the type, so you have to get it separately than the field: listingType := reflect.TypeOf(*l). Then you can get the indexed field and the tag from that.

提交回复
热议问题