如何将 reflect.Value 转换为其类型?

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

How to cast reflect.Value to its type?

问题

如何将 reflect.Value 转换为其类型?

type Cat struct { 
    Age int
}

cat := reflect.ValueOf(obj)
fmt.Println(cat.Type()) // Cat

fmt.Println(Cat(cat).Age) // 无法编译通过
fmt.Println((cat.(Cat)).Age) // 相同

谢谢!

英文:

How to cast reflect.Value to its type?

type Cat struct { 
    Age int
}

cat := reflect.ValueOf(obj)
fmt.Println(cat.Type()) // Cat

fmt.Println(Cat(cat).Age) // doesn't compile
fmt.Println((cat.(Cat)).Age) // same

Thanks!

答案1

得分: 89

concreteCat,_ := reflect.ValueOf(cat).Interface().(Cat)

请参考http://golang.org/doc/articles/laws_of_reflection.html
例如

type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
y := v.Interface().(float64) // y将具有float64类型。
fmt.Println(y)
英文:
concreteCat,_ := reflect.ValueOf(cat).Interface().(Cat)

see http://golang.org/doc/articles/laws_of_reflection.html
fox example

type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)

答案2

得分: 44

reflect.Value有一个名为Interface()的函数,可以将其转换为interface{}类型。

英文:

Ok, I found it

reflect.Value has a function Interface() that converts it to interface{}

答案3

得分: 5

这个函数根据需要自动转换类型。它根据结构体的名称和字段将配置文件的值加载到一个简单的结构体中:

import (
	"fmt"
	toml "github.com/pelletier/go-toml"
	"log"
	"os"
	"reflect"
)
func LoadConfig(configFileName string, configStruct interface{}) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("LoadConfig.Recovered: ", r)
		}
	}()
	conf, err := toml.LoadFile(configFileName)
	if err == nil {
		v := reflect.ValueOf(configStruct)
		typeOfS := v.Elem().Type()
		sectionName := getTypeName(configStruct)
		for i := 0; i < v.Elem().NumField(); i++ {
			if v.Elem().Field(i).CanInterface() {
				kName := conf.Get(sectionName + "." + typeOfS.Field(i).Name)
				kValue := reflect.ValueOf(kName)
				if (kValue.IsValid()) {
					v.Elem().Field(i).Set(kValue.Convert(typeOfS.Field(i).Type))
				}
			}
		}
	} else {
		fmt.Println("LoadConfig.Error: " + err.Error())
	}
}
英文:

This func auto-converts types as needed. It loads a config file values into a simple struct based on struct name and fields:

import (
	&quot;fmt&quot;
	toml &quot;github.com/pelletier/go-toml&quot;
	&quot;log&quot;
	&quot;os&quot;
	&quot;reflect&quot;
)
func LoadConfig(configFileName string, configStruct interface{}) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println(&quot;LoadConfig.Recovered: &quot;, r)
		}
	}()
	conf, err := toml.LoadFile(configFileName)
	if err == nil {
		v := reflect.ValueOf(configStruct)
		typeOfS := v.Elem().Type()
		sectionName := getTypeName(configStruct)
		for i := 0; i &lt; v.Elem().NumField(); i++ {
			if v.Elem().Field(i).CanInterface() {
				kName := conf.Get(sectionName + &quot;.&quot; + typeOfS.Field(i).Name)
				kValue := reflect.ValueOf(kName)
				if (kValue.IsValid()) {
					v.Elem().Field(i).Set(kValue.Convert(typeOfS.Field(i).Type))
				}
			}
		}
	} else {
		fmt.Println(&quot;LoadConfig.Error: &quot; + err.Error())
	}
}

答案4

得分: 2

func valuesFromStruct(rawV interface{}) []interface{} {
v := reflect.ValueOf(rawV)
out := make([]interface{}, 0)
for i := 0; i < v.NumField(); i += 1 {
field := v.Field(i)
fieldType := field.Type()
switch fieldType.Name() {
case "int64":
out = append(out, field.Interface().(int64))
break
case "float64":
out = append(out, field.Interface().(float64))
break
case "string":
out = append(out, field.Interface().(string))
break
// And all your other types (here) ...
default:
out = append(out, field.Interface())
break
}
}
return out
}

英文:

Seems the only way would be to do a switch statement similar to (code below) (also, something like the commented line would've-been nice though doesn't work (:()):

func valuesFromStruct (rawV interface{}) []interface{} {
	v := reflect.ValueOf(rawV)
	out := make([]interface{}, 0)
	for i := 0; i &lt; v.NumField(); i += 1 {
		field := v.Field(i)
		fieldType := field.Type()
		// out = append(out, field.Interface().(reflect.PtrTo(fieldType)))
		switch (fieldType.Name()) {
		case &quot;int64&quot;:
			out = append(out, field.Interface().(int64))
			break`enter code here`
		case &quot;float64&quot;:
			out = append(out, field.Interface().(float64))
			break
		case &quot;string&quot;:
			out = append(out, field.Interface().(string))
			break
        // And all your other types (here) ...
		default:
			out = append(out, field.Interface())
			break
		}
	}
	return out
}

Cheers!

huangapple
  • 本文由 发表于 2013年6月23日 23:23:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/17262238.html
匿名

发表评论

匿名网友

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

确定