如何根据结构字段类型对值进行类型转换?

我正在尝试创建一个填充给定字段的方法struct,但是要设置正确的值,我需要转换值以检查类型是否与结构字段类型匹配。


例子:


type S struct {

    Name string

    Age int

}

该值将始终是string因为它来自 URL。


const stubQuery = "name=sam&page=30"

query, _ := url.ParseQuery(stubQuery)

// e.g result: {"name": ["sam"], "age": ["30"]}

我已经设法迭代query并从S结构中获取字段,但是我怎样才能获取字段类型并将“30”转换为结构类型?


structValue := reflect.ValueOf(&S{}).Elem()

structFieldValue := structValue.FieldByName("Age")


structFieldType := structFieldValue.Type()

val := reflect.ValueOf("30")


if structFieldType != val.Type() {} // Always false


九州编程
浏览 128回答 2
2回答

UYOU

应用程序必须将字符串解析为可分配给该字段的值。使用类型开关和值开关查找要解析的类型或种类。使用strconv 包解析数值和布尔值。使用time 包来解析时间和持续时间。这是一些示例代码:v := reflect.ValueOf(&s).Elem()t := v.Type()for i := 0; i < t.NumField(); i++ {&nbsp; &nbsp; sf := t.Field(i)&nbsp; &nbsp; // Get value from query. Skip if not set.&nbsp; &nbsp; values, ok := query[strings.ToLower(sf.Name)]&nbsp; &nbsp; if !ok || len(values) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; }&nbsp; &nbsp; // Use type switch for specific types.&nbsp; &nbsp; switch f := v.Field(i).Addr().Interface().(type) {&nbsp; &nbsp; case *time.Time:&nbsp; &nbsp; &nbsp; &nbsp; var err error&nbsp; &nbsp; &nbsp; &nbsp; *f, err = time.Parse(time.RFC3339, values[0])&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; case *time.Duration:&nbsp; &nbsp; &nbsp; &nbsp; var err error&nbsp; &nbsp; &nbsp; &nbsp; *f, err = time.ParseDuration(values[0])&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; // The specific type was not handled. Fallback&nbsp; &nbsp; &nbsp; &nbsp; // to using the field kind. This allows us to&nbsp; &nbsp; &nbsp; &nbsp; // handle all numeric and bool types without knowing&nbsp; &nbsp; &nbsp; &nbsp; // those types explicitly.&nbsp; &nbsp; &nbsp; &nbsp; switch sf.Type.Kind() {&nbsp; &nbsp; &nbsp; &nbsp; case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n, err := strconv.ParseInt(values[0], 10, sf.Type.Bits())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v.Field(i).SetInt(n)&nbsp; &nbsp; &nbsp; &nbsp; case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n, err := strconv.ParseUint(values[0], 10, sf.Type.Bits())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v.Field(i).SetUint(n)&nbsp; &nbsp; &nbsp; &nbsp; case reflect.Float64, reflect.Float32:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n, err := strconv.ParseFloat(values[0], sf.Type.Bits())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v.Field(i).SetFloat(n)&nbsp; &nbsp; &nbsp; &nbsp; case reflect.Bool:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b, err := strconv.ParseBool(values[0])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v.Field(i).SetBool(b)&nbsp; &nbsp; &nbsp; &nbsp; case reflect.String:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v.Field(i).SetString(values[0])&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("unknown type")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}首先检查类型,以便将 time.Duration 解析为持续时间而不是整数。将 log.Fatal 调用替换为适合您的场景的错误处理。

牧羊人nacy

val := reflect.ValueOf("30")传入参数的类型("30"在您的示例代码中)是string。它的类型永远不会匹配数字字段的类型。你必须检查structFieldType,以确定你应该应用什么转换val。另一种方法可能是向您的结构添加一个特定的方法来填充它的字段:AssignFields(in url.Values) error# orAssignField(name string, value string) error
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go