动态添加值

时间:2016-02-04 23:06:28

标签: go

我正在尝试创建一个查看结构元数据的服务,并将确定要添加到哪些字段。这是一个示例Struct和我在Go Playground中用来将各种东西添加到一起的函数。这只是一个示例结构,显然并非所有字段都会递增。

恐慌是“恐慌:界面转换:界面是int,而不是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)
}

游乐场:https://play.golang.org/p/QghY01QY13

1 个答案:

答案 0 :(得分:2)

由于字段的类型为int,因此您必须键入assert为int

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

playground example

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

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

playground example

以下是所有数字类型的操作方法:

        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 example