当前位置: 首页 > 面试题库 >

遍历Struct中的字符串字段

纪佐
2023-03-14
问题内容

我在寻找一个struct的字符串字段遍历,所以我可以做一些清理/验证(与strings.TrimSpacestrings.Trim等)。

现在,我有一个混乱的开关盒,它并没有真正的可扩展性,而且由于这并不是我的应用程序(Web表单)的热点,因此reflect在这里利用杠杆作用似乎是一个不错的选择。

我对于如何实现此功能有点障碍,反射文档对我来说有点困惑(我一直在研究其他一些验证包,但是它们太笨重了,我正在使用大猩猩/模式已用于解组部分):

  • 遍历该结构
  • 对于字符串类型的每个字段,请从strings包中应用我需要的任何内容,即field = strings.TrimSpace(field)
  • 如果存在field.Tag.Get(“ max”),我们将使用该值(strconv.Atoi,然后unicode.RuneCountInString)
  • 提供也与错误接口类型兼容的错误片
        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 {

           typ := l.Elem().Type()

           var invalid FormError
           for i = 0; i < typ.NumField(); i++ {
               // Iterate over fields
               // For StructFields of type string, field = strings.TrimSpace(field)
               // if field.Tag.Get("max") != "" {
               //     check max length/convert to int/utf8.RuneCountInString
                      if max length exceeded, invalid = append(invalid, "errormsg")
           }

           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
       }

提前致谢。


问题答案:

您想要的主要是reflect.Value上称为NumFields() int和的方法Field(int)。您唯一真正缺少的是字符串检查和SetString方法。

    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)
    }

(游乐场链接)

这里有两个警告:

  1. 您需要一个指向要更改的指针。如果有值,则需要返回修改后的结果。

  2. 尝试修改未导出的字段通常会引起反射恐慌。如果您打算修改未导出的字段,请确保在包内执行此操作。

该代码相当灵活,如果您需要根据类型的不同行为,则可以使用switch语句或类型switch(在field.Interface()返回的值上)。

编辑:至于标记行为,您似乎已经知道了。一旦有了字段并检查了它是否是字符串,就可以field.Tag.Get("max")从那里使用并解析它。

Edit2:我在标签上犯了一个小错误。标签是反射类型的一部分。结构的类型,因此可以使用它们(有点麻烦)msValue.Type().Field(i).Tag.Get("max")

(您在注释中发布的带有有效Tag的代码的Playground版本)。



 类似资料:
  • 问题内容: 我有这样定义的多行字符串: 我们用作我正在编写的解析器的测试输入的字符串。解析器功能接收-object作为输入并对其进行迭代。它还确实直接调用该方法以跳过行,因此我确实需要一个迭代器作为输入,而不是可迭代的。我需要一个迭代器,它可以在字符串的各个行之间进行迭代,就像-object可以在文本文件的行之间进行迭代一样。我当然可以这样: 是否有更直接的方法?在这种情况下,字符串必须遍历一次以

  • 问题内容: 如何遍历Java中的字符串? 我正在尝试使用foreach样式进行循环 问题答案: 如果要使用增强循环,可以将字符串转换为charArray

  • 问题内容: 我想知道如何逐字地遍历一个字符串。 上面给出了输出: 但是我正在寻找以下输出: 问题答案: 当你做- 您不是在遍历字符串中的单词,而是在遍历字符串中的字符。要遍历单词,您首先需要使用将字符串拆分成单词,然后遍历该单词。范例- 请注意,,且不传递任何参数,所有空格都将其分割(空格,多个空格,制表符,换行符等)。

  • 问题内容: 我想遍历s1以确保s1中的每个字符都包含在s2中。 问题答案:

  • 问题内容: 我有一个允许用户上载文本文件或将文件内容复制/粘贴到文本区域的表格。我可以轻松地区分两者,然后将它们输入的任何一个放入字符串变量中,但是我从那里去哪里呢? 我需要遍历字符串的每一行(最好不要担心不同机器上的换行符),确保它只有一个令牌(没有空格,制表符,逗号等),清理数据,然后生成一个SQL查询基于所有方面。 我是一个非常优秀的程序员,所以我知道如何做的一般想法,但是自从使用PHP以来