英文:
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 (
"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
答案1
得分: 2
因为这些字段的类型是int
,所以你必须使用类型断言为int
。
reflect.ValueOf(&new).Elem().Field(i).SetInt(int64(new_values.Field(i).Interface().(int) + values.Field(i).Interface().(int)))
另一种方法是使用Int()而不是Interface().(int)。这种方法适用于所有有符号整数类型:
reflect.ValueOf(&new).Elem().Field(i).SetInt(new_values.Field(i).Int() + values.Field(i).Int())
以下是适用于所有数值类型的示例:
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())
}
英文:
Because the fields are of type int
, you must type assert to int
.
reflect.ValueOf(&new).Elem().Field(i).SetInt(int64(new_values.Field(i).Interface().(int) + values.Field(i).Interface().(int)))
Another approach is to use the Int() instead of Interface().(int). This approach works with all signed integer types:
reflect.ValueOf(&new).Elem().Field(i).SetInt(new_values.Field(i).Int() + values.Field(i).Int())
Here's how to do it for all numeric types:
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())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论