Go

时间:2016-12-09 10:58:57

标签: go

我是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
}

是否有可能获得更多动态,以便我不需要复制代码,并且下面的示例中只有一个函数?

1 个答案:

答案 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(),否则将无法设置。

如果键值不等于字段名称,我们可以创建从实际键值到目标字段名称的映射,因此在索引此映射后再次获取目标字段将是相同的。此解决方案还为我们提供了某种保护:如果键值不在地图中,我们就不会更改任何字段。