追加到使用反射
问题描述:
一个结构体的片场我有一个struct
,看起来像这样:追加到使用反射
type guitaristT struct {
Surname string `required=true`
Year int64 `required=false`
American bool // example of missing tag
Rating float32 `required=true`
Styles []string `required=true,minsize=1`
}
我有一个环境变量,如下所示,和我使用反射来填充结构基于密钥。
jimiEnvvar :="surname=Hendrix|year=1942|american=true|rating=9.99
|styles=blues|styles=rock|styles=psychedelic"
我能够设置使用反射string, int64, bool and float32
领域,但我坚持就如何追加到slice
场样式。例如,根据上述jimiEnvvar
我希望字段jimi.Styles
的值为["blues","rock", "psychedelic"]
。
我有以下(简化的)代码:
result := guitaristT{}
// result.Styles = make([]string, 10) // XXX causes 10 empty strings at start
result.Styles = make([]string, 0) // EDIT: Alessandro's solution
...
v := reflect.ValueOf(&result).Elem()
...
field := v.FieldByName(key) // eg key = "styles"
...
switch field.Kind() {
case reflect.Slice:
// this is where I get stuck
//
// reflect.Append() has signature:
// func Append(s Value, x ...Value) Value
// so I convert my value to a reflect.Value
stringValue := reflect.ValueOf(value) // eg value = "blues"
// field = reflect.Append(field, stringValue) // XXX doesn't append
field.Set(reflect.Append(field, stringValue)) // EDIT: Alessandro's solution
编辑:
的第二部分(我解决)被填充在该结构的地图。例如:
type guitaristT struct {
...
Styles []string `required=true,minsize=1`
Cities map[string]int
}
凡jimiEnvvar样子:
case reflect.Map:
fmt.Println("keyAsString", keyAsString, "is Map, has value:", valueAsString)
mapKV := strings.Split(valueAsString, "^")
if len(mapKV) != 2 {
log.Fatalln("malformed map key/value:", mapKV)
}
mapK := mapKV[0]
mapV := mapKV[1]
thisMap := fieldAsValue.Interface().(map[string]int)
thisMap[mapK] = atoi(mapV)
thisMapAsValue := reflect.ValueOf(thisMap)
fieldAsValue.Set(thisMapAsValue)
The final result was:
main.guitaristT{
Surname: "Hendrix",
Year: 1942,
American: true,
Rating: 9.989999771118164,
Styles: {"blues", "rock", "psychedelic"},
Cities: {"London":11, "Bay Area":9, "New York":17, "Los Angeles":14},
}
:
jimiEnvvar += "|cities=New York^17|cities=Los Angeles^14"
我这样写道:如果您有兴趣,完整的代码是https://github.com/soniah/reflect/blob/master/structs.go。代码只是我正在写的一些笔记/练习。
EDIT2:
的第11章 “在实践中去”(屠夫和法里纳)有详细的反映,结构和标签说明。
答
你不是太遥远。只需更换为
field.Set(reflect.Append(field, stringValue))
你就完成了。此外,请确保您,您使用
result.Styles = make([]string, 0)
初始化切片或你最终将在Styles
阵列的顶部具有10个空字符串。
希望这有助于您的项目,祝您好运。
感谢您的回答亚历山德罗。今天,我在上面附加的地图代码上工作。它的工作原理,但也许你有一些改进它的意见? –