动态地将值相加在一起

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

Dynamically add values together

问题

我正在尝试创建一个服务,该服务查看结构体的元数据,并确定要添加在一起的字段。这是一个示例结构体和我在Go Playground中使用的函数,用于将这些字段相加。这只是一个示例结构体,显然不是所有字段都会递增。

出现了"panic: interface conversion: interface is int, not int64"的错误,我应该如何正确处理?

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

type TestResult struct {
	Complete         int     `json:"complete" increment:"true"`
	Duration         int     `json:"duration" increment:"true"`
	Failed           int     `json:"failed" increment:"true"`
	Mistakes         int     `json:"mistakes" increment:"true"`
	Points           int     `json:"points" increment:"true"`
	Questions        int     `json:"questions" increment:"true"`
	Removal_duration int     `json:"removal_duration" increment:"true"`
}

func main() {
	old := TestResult{}
	new := TestResult{}

	old.Complete = 5
	new.Complete = 10

	values := reflect.ValueOf(old)
	new_values := reflect.ValueOf(new)
	value_type := reflect.TypeOf(old)
	fmt.Println(values)
	fmt.Println(new_values)

	for i := 0; i < values.NumField(); i++ {
		field := value_type.Field(i)
		if increment, err := strconv.ParseBool(field.Tag.Get("increment")); err == nil && increment {
			reflect.ValueOf(&new).Elem().Field(i).SetInt(new_values.Field(i).Interface().(int64) + values.Field(i).Interface().(int64))
		}
	}
	fmt.Println(new)
}

Playground链接:https://play.golang.org/p/QghY01QY13

英文:

I am trying to create a service that looks at structs meta data and will figure out which fields to add together. Here is a sample Struct and the function I have been using in Go Playground to add things together. This is a just a sample struct, obviously not all fields would be increment.

It is panic with "panic: interface conversion: interface is int, not int64", how do I do this the right way?

package main

import (
   &quot;fmt&quot;
   &quot;reflect&quot;
   &quot;strconv&quot;
)

type TestResult struct {
	Complete         int    	`json:&quot;complete&quot; increment:&quot;true&quot;`
	Duration         int    	`json:&quot;duration&quot; increment:&quot;true&quot;`
	Failed           int    	`json:&quot;failed&quot; increment:&quot;true&quot;`
	Mistakes         int    	`json:&quot;mistakes&quot; increment:&quot;true&quot;`
	Points           int    	`json:&quot;points&quot; increment:&quot;true&quot;`
	Questions        int    	`json:&quot;questions&quot; increment:&quot;true&quot;`
	Removal_duration int    	`json:&quot;removal_duration&quot; increment:&quot;true&quot;`
}

func main() {
	old := TestResult{}
	new := TestResult{}
	
	old.Complete = 5
	new.Complete = 10
	
	values := reflect.ValueOf(old)
	new_values := reflect.ValueOf(new)
	value_type := reflect.TypeOf(old)
	fmt.Println(values)
	fmt.Println(new_values)
	
	for i := 0; i &lt; values.NumField(); i++ {
	   field := value_type.Field(i)
	   if increment, err := strconv.ParseBool(field.Tag.Get(&quot;increment&quot;)); err == nil &amp;&amp; increment {
	      reflect.ValueOf(&amp;new).Elem().Field(i).SetInt(new_values.Field(i).Interface().(int64) + values.Field(i).Interface().(int64))
	   }
	}
	fmt.Println(new)
}

Playground: https://play.golang.org/p/QghY01QY13

答案1

得分: 2

因为这些字段的类型是int,所以你必须使用类型断言为int

reflect.ValueOf(&new).Elem().Field(i).SetInt(int64(new_values.Field(i).Interface().(int) + values.Field(i).Interface().(int)))

playground 示例

另一种方法是使用Int()而不是Interface().(int)。这种方法适用于所有有符号整数类型:

reflect.ValueOf(&new).Elem().Field(i).SetInt(new_values.Field(i).Int() + values.Field(i).Int())

playground 示例

以下是适用于所有数值类型的示例:

v := reflect.ValueOf(&new).Elem().Field(i)
switch v.Kind() {
case reflect.Int,
	reflect.Int8,
	reflect.Int16,
	reflect.Int32,
	reflect.Int64:
	v.SetInt(new_values.Field(i).Int() + values.Field(i).Int())
case reflect.Uint,
	reflect.Uint8,
	reflect.Uint16,
	reflect.Uint32,
	reflect.Uint64:
	v.SetUint(new_values.Field(i).Uint() + values.Field(i).Uint())
case reflect.Float32, reflect.Float64:
	v.SetFloat(new_values.Field(i).Float() + values.Field(i).Float())
}

playground 示例

英文:

Because the fields are of type int, you must type assert to int.

reflect.ValueOf(&amp;new).Elem().Field(i).SetInt(int64(new_values.Field(i).Interface().(int) + values.Field(i).Interface().(int)))

playground example

Another approach is to use the Int() instead of Interface().(int). This approach works with all signed integer types:

reflect.ValueOf(&amp;new).Elem().Field(i).SetInt(new_values.Field(i).Int() + values.Field(i).Int())

playground example

Here's how to do it for all numeric types:

		v := reflect.ValueOf(&amp;new).Elem().Field(i)
		switch v.Kind() {
		case reflect.Int,
			reflect.Int8,
			reflect.Int16,
			reflect.Int32,
			reflect.Int64:
			v.SetInt(new_values.Field(i).Int() + values.Field(i).Int())
		case reflect.Uint,
			reflect.Uint8,
			reflect.Uint16,
			reflect.Uint32,
			reflect.Uint64:
			v.SetUint(new_values.Field(i).Uint() + values.Field(i).Uint())
		case reflect.Float32, reflect.Float64:
			v.SetFloat(new_values.Field(i).Float() + values.Field(i).Float())
		}

playground example

huangapple
  • 本文由 发表于 2016年2月5日 07:06:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/35213411.html
匿名

发表评论

匿名网友

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

确定