【问题标题】:Parse and validate "key1:value1; key2:value2" string to Go struct efficiently?有效地解析和验证“key1:value1; key2:value2”字符串到 Go 结构?
【发布时间】:2018-07-01 09:19:40
【问题描述】:

我有一个“key1:value1; key2:value2”之类的字符串(key:value 模式的字符串由; 连接)。

现在我希望将此字符串解析为 Go 结构:

type CustomStruct struct {
   KeyName1 string `name:"key1" somevalidation:"xxx"`
   KeyName2 int    `name:"key2" somevalidation:"yyy"`
}

在上面的例子中,struct标签定义了字符串中key的名称,并且可以为其对应的值提供一些验证(如果验证失败,它可以设置一个默认值)。例如,KeyName2 是一个int 值,所以我希望somevalidation 可以检查KeyName2 是否满足,比如说,大于30 小于等于100。

在另一个场景中,我可以为 key3:value3; key4:value4; 之类的字符串定义另一个结构 CustomStruct2

如何高效优雅地归档此类需求?

【问题讨论】:

  • @ThunderCat 我不知道它是否是众所周知的格式。我对字符串的看法是:key:value 模式的字符串由; 连接。基本上字符串可以被认为是一个 map[string]string

标签: go


【解决方案1】:

我假设您可以将数据解析为 map[string]interface{}。

使用reflect 包设置字段。这是基本功能:

// set sets fields in struct pointed to by pv to values in data.
func set(pv interface{}, data map[string]interface{}) {
    // pv is assumed to be pointer to a struct
    s := reflect.ValueOf(pv).Elem()

    // Loop through fields
    t := s.Type()
    for i := 0; i < t.NumField(); i++ {

        // Set field if there's a data value for the field.
        f := t.Field(i)
        if d, ok := data[f.Tag.Get("name")]; ok {
            s.Field(i).Set(reflect.ValueOf(d))
        }
    }
}

此代码假定数据映射中的值可分配给结构中的相应字段,并且第一个参数是指向结构的指针。如果这些假设不成立,代码将会恐慌。您可以通过使用反射包检查类型和可分配性来防止这种情况发生。

playground example

【讨论】:

  • 非常感谢!我想这是我第一次使用 go reflect
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 2015-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多