英文:
Accessing struct field by a given string that contains the full path
问题
如果你想使用字符串来访问结构体中指定的字段,你可以使用反射(Reflect)包来实现。首先,你需要使用reflect.ValueOf()
函数获取结构体的反射值。然后,你可以使用FieldByName()
方法来获取指定字段的反射值。下面是一个示例代码:
package main
import (
"fmt"
"reflect"
)
type Stream struct {
Fields []Field
}
type Field struct {
Name string
}
func main() {
stream := Stream{
Fields: []Field{
{Name: "Field 1"},
{Name: "Field 2"},
},
}
fieldName := "Stream.Fields[0].Name"
// 获取结构体的反射值
streamValue := reflect.ValueOf(stream)
// 使用字符串访问指定字段的反射值
fieldValue := getFieldByString(streamValue, fieldName)
// 输出字段的值
fmt.Println(fieldValue.Interface())
}
func getFieldByString(v reflect.Value, fieldName string) reflect.Value {
// 按照点号分割字段名
fieldNames := strings.Split(fieldName, ".")
// 逐级获取字段的反射值
for _, name := range fieldNames {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
v = v.FieldByName(name)
}
return v
}
在上面的示例中,我们定义了一个Stream
结构体和一个Field
结构体。然后,我们创建了一个Stream
实例,并给fieldName
赋值为"Stream.Fields[0].Name"
。通过调用getFieldByString()
函数,我们可以获取到指定字段的反射值,并将其输出到控制台上。
请注意,这只是一个简单的示例,实际使用中可能需要根据具体情况进行适当的修改。希望对你有帮助!
英文:
A validator package gives me back strings like this if a given field in my struct doesn't pass the validation:
myString := "Stream.Fields[0].Name"
How can i use this string to gain access to the struct field specified in it? I need to reference it somehow but i have no idea where to start with.
I'm beginning to learn Go and already came across the "Reflect" package which seems to be able to do that but i don't know what to look for or how to formulate the right question.
答案1
得分: 6
你需要使用reflect包来实现这个功能。下面是一个示例函数,给定一个实例和字符串键(例如Stream.Details.Name
),它将返回实例Stream
中Details
字段的Name
值。
这个函数适用于没有array
或map
操作符的结构体,只有.
操作符。你可以扩展它以支持[]
操作符。
func getValueFromStruct(keyWithDots string, object interface{}) (interface{}, error) {
keySlice := strings.Split(keyWithDots, ".")
v := reflect.ValueOf(object)
// 遍历字段名,忽略第一个字段名,因为它可能是当前实例的名称
// 如果想支持像slice、map等类型的结构体,可以将其改为递归函数
for _, key := range keySlice[1:] {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
// 只接受结构体类型
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("只接受结构体类型;当前类型为 %T", v)
}
v = v.FieldByName(key)
}
return v, nil
}
这是一个Go Playground的链接:https://play.golang.org/p/NIRdGONZBhP
英文:
You need to use reflect package for this.
Here I have written a sample function which given an instance and string key like Stream.Details.Name
will return the Name
from the field Details of instance Stream
This works for structs without array
or map
operators , just the .
operator . You may extend this to support the []
aswell
func getValueFromStruct(keyWithDots string, object interface{}) (interface{}, error) {
keySlice := strings.Split(keyWithDots, ".")
v := reflect.ValueOf(object)
// iterate through field names ,ignore the first name as it might be the current instance name
// you can make it recursive also if want to support types like slice,map etc along with struct
for _, key := range keySlice[1:] {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
// we only accept structs
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("only accepts structs; got %T", v)
}
v = v.FieldByName(key)
}
return v, nil
}
Here is golang play link : https://play.golang.org/p/NIRdGONZBhP
答案2
得分: 0
这个库也存在,可能可以满足你的需求:
https://github.com/mcuadros/go-lookup
该库在底层使用了reflect包。
英文:
This library also exists, which might do what you want:
https://github.com/mcuadros/go-lookup
The lib uses the reflect package under the hood.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论