我是Go的新手,我非常喜欢静态类型检查,它已经在编译阶段保存了几次我的培根!
然而,我确实看到我复制了许多代码,例如......if string(key) == "altitude" {
altitudeInt, _ := jsonparser.ParseInt(value)
n.ThisDataRaw.Altitude = new(int)
*n.ThisDataRaw.Altitude = int(altitudeInt)
return nil
}
if string(key) == "heading" {
headingInt, _ := jsonparser.ParseInt(value)
n.ThisDataRaw.Heading = new(int)
*n.ThisDataRaw.Heading = int(headingInt)
return nil
}
if string(key) == "speed" {
speedInt, _ := jsonparser.ParseInt(value)
n.ThisDataRaw.Speed = new(int)
*n.ThisDataRaw.Speed = int(speedInt)
return nil
}
是否有可能获得更多动态,以便我不需要复制代码,并且下面的示例中只有一个函数?
答案 0 :(得分:7)
没有任何“魔法”,您的代码可以简化为:
parsed, err := jsonparser.ParseInt(value)
// check err
switch intValue := int(parsed); key {
case "altitude":
n.ThisDataRaw.Altitude = &intValue
case "heading":
n.ThisDataRaw.Heading = &intValue
case "speed":
n.ThisDataRaw.Speed = &intValue
}
它更清晰,包含最少的代码冗余。如果n.ThisDataRaw
字段是指针,我们可以做更多的事情:
parsed, err := jsonparser.ParseInt(value)
// check err
switch intValue, tdr := int(parsed), n.ThisDataRaw; key {
case "altitude":
tdr.Altitude = &intValue
case "heading":
tdr.Heading = &intValue
case "speed":
tdr.Speed = &intValue
}
如果n.ThisDataRaw
字段不是指针,我们仍然可以通过获取其地址来应用最后一步:
switch intValue, tdr := int(parsed), &n.ThisDataRaw; key {
(其余代码是相同的。)
你应该对此感到满意。如果没有,请继续阅读。
如果识别结构字段的数据是string
,我们要么必须使用某种分支(如上面的switch
),要么我们可以使用反射来获取基于的字段string
值。
注意:使用反射而不是switch
,我们冒险设置我们不想要的字段。反思也会使它变得更慢,更难理解。如果字段数不大,只需使用switch
。
如果键值等于字段名称,这将非常简单,但请确保将指针传递给reflect.ValueOf()
,否则将无法设置。
如果键值不等于字段名称,我们可以创建从实际键值到目标字段名称的映射,因此在索引此映射后再次获取目标字段将是相同的。此解决方案还为我们提供了某种保护:如果键值不在地图中,我们就不会更改任何字段。