我在Go to a中解组JSON map[string]interface{}并使用接口的混合字符串,float和slice值来填充PlaceNode结构的字段值.
我需要类似"默认值"的东西,因为并非所有JSON对象都具有所有Struct字段.来自其他语言背景,Structs是可索引的我会习惯做这样的事情来设置n Placenode变量的值(例如,好像它是JavaScript 中的一个self或this关键字).
n[key] = value;
Run Code Online (Sandbox Code Playgroud)
相反,我在我的PlaceNodestruct 上有一个方法来读取interface{},使用reflect并可选地分配一个值,如果可以设置该字段.我interfaces{}没有实现所有的值,所以我很难直接进入我的结构.
显然没有一个字段通过此s.CanSet()检查.所以我一定是在犯这个错误.
如何在Go中设置动态结构字段?
func (n PlaceNode) New(data map[string]interface{}) PlaceNode {
for key, val := range data {
n.Id = key
for k, v := range val.(map[string]interface{}) {
f := reflect.ValueOf(v)
st := reflect.ValueOf(n)
if (st.Kind() == reflect.Struct) {
s := st.FieldByName(k)
if f.Kind() == reflect.String && true == s.CanSet() {
s.SetString(f.String());
} else if f.Kind() == reflect.Float64 && true == s.CanSet() {
s.SetFloat(f.Float());
} else if f.Kind() == reflect.Slice && true == s.CanSet() {
s.Set(f.Slice(0, f.Len()));
}
}
}
}
return n
}
Run Code Online (Sandbox Code Playgroud)
该data参数map[string]interface{}的接口也是a map[string]interface{},如下所示:
{
"XV.12A": {
"Area": 1189.132667,
"CensusBlock": 2032,
"CensusBlockGroup": 2,
"CensusCbsaFips": 40900,
"CensusCountyFips": 61,
"CensusMcdFips": 90160,
"CensusMsaFips": 6922,
"CensusPlaceFips": 3204,
"CensusStateFips": 6,
"CensusTract": 203,
"CensusYear": 2010,
"Radius": 19.455402434548,
"RegionSize": 1189.132667
}
}
Run Code Online (Sandbox Code Playgroud)
当您拨打以下电话时:
st := reflect.ValueOf(n)
Run Code Online (Sandbox Code Playgroud)
ValueOf传递PlaceNode结构的副本.所以所做的任何改变st都不会被看到n.因此,包将此类情况视为不可寻址的值.如果你想要一个reflect.Value代表n,请尝试使用这样的东西:
st := reflect.ValueOf(&n).Elem()
Run Code Online (Sandbox Code Playgroud)
现在st直接使用n而不是副本,并且是可寻址的.您现在应该可以使用Set*它及其字段的各种方法.