使用Go语言更加动态一些

huangapple go评论75阅读模式
英文:

Being a little more dynamic with 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
}

是否有可能使代码更加动态化,以便我不需要重复编写这些代码,并且在下面的示例中只需要一个函数呢?

英文:

I'm new to Go and I do like the static type checking a lot, it has saved my bacon a few times already at compile phase!

I do however see that I am duplicating a lot of code such as...

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
}

Is it possible to get a little bit more dynamic so that I don't need to duplicate the code and for the example below have a single function at all?

答案1

得分: 7

没有任何“魔法”,你的代码可以简化为以下形式:

parsed, err := jsonparser.ParseInt(value)
// 检查错误
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)
// 检查错误
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 {

(代码的其余部分保持不变。)

这样应该能满足你的需求。如果不满意,请继续阅读。

如果用于标识结构字段的数据是一个字符串,我们要么使用某种分支结构(如上面的switch),要么可以使用反射根据字符串值获取字段。

注意:使用反射而不是switch,我们可能会设置我们不想要的字段。而且反射会使代码变慢,更难理解。如果字段数量不大,只需使用switch

如果键值等于字段名,这将非常简单,但一定要传递一个指向reflect.ValueOf()的指针,否则它将无法设置。

如果键值不等于字段名,我们可以创建一个从实际键值到目标字段名的映射,这样在索引该映射后获取目标字段将是相同的。这种解决方案还提供了一定的保护:如果键值不在映射中,我们将不会更改任何字段。

英文:

Without any "magic", your code can be simplified to this:

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
}

It's much cleaner and contains minimal code redundancy. If the n.ThisDataRaw field is a pointer, we can do a little more:

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
}

If the n.ThisDataRaw field is not a pointer, we can still apply this last step, by taking its address:

switch intValue, tdr := int(parsed), &n.ThisDataRaw; key {

(The rest of the code is the same.)

You should be satisfied by this. If not, read on.

If the data identifying your struct field comes as a string, we either have to use some kind of branching (like the switch above), or we may use reflection to get the field based on the string value.

Note: using reflection instead of the switch, we'd risk setting fields which otherwise we would not want to. Also reflection will make it slower, and harder to understand. If the number of fields is not big, just use the switch.

If the key value equals to the field name, this would be very simple, but be sure to pass a pointer to reflect.ValueOf(), else it won't be settable.

If the key value does not equal to the field name, we could create a mapping from the actual key values to the target field names, so again after indexing this map getting the target field would be the same. This solution also gives us some kind of protection: if the key value is not in the map, we would not change any fields.

huangapple
  • 本文由 发表于 2016年12月9日 18:58:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/41058872.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定