How to cast reflect.Value to its type?

本文介绍如何在Go语言中使用反射将reflect.Value类型转换回其原始的具体类型,并提供了具体的代码示例。

转载自 https://stackoverflow.com/questions/17262238/how-to-cast-reflect-value-to-its-type

43

 

9

 

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!

reflectiongo

share  improve this question  follow 

asked Jun 23 '13 at 15:23

 

Alex

29k2121 gold badges8080 silver badges127127 bronze badges

add a comment

4 Answers

ActiveOldestVotes

54

 

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)

share  improve this answer  follow 

edited Jun 14 '14 at 10:18

Benjamin

29.3k3838 gold badges152152 silver badges273273 bronze badges

answered Dec 19 '13 at 8:05

 

sharewind

1,54133 gold badges1313 silver badges1212 bronze badges

  • 15

    That's if you actually have knowledge of the type. In the case you would like to apply kind of a blind type assertion, I'm actually not sure it is possible. – Taye Aug 17 '14 at 11:00

  • One solution seems to be to leave the reflect.Value as-is and simply move all your calculations to using the reflect package without hope of ever converting to back to a regular struct. You can see this in gongular. Related: play.golang.org/p/Ok_q3lx490h – Xeoncross Mar 1 '18 at 4:28

  • 2

    It doesn't work. panic: interface conversion: interface {} is main.MyInt, not float64 – TomSawyer May 3 '18 at 19:47

add a comment

33

 

Ok, I found it

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

share  improve this answer  follow 

edited Jun 23 '13 at 16:37

fuz

72.8k2323 gold badges154154 silver badges296296 bronze badges

answered Jun 23 '13 at 15:32

Alex

29k2121 gold badges8080 silver badges127127 bronze badges

  • 19

    That converts it to interface{}. How do we convert it to the actual type? – Matt Dec 4 '13 at 16:40

  • 1

    It's not possible in Go, @Matt. You can't reinvent generics without unsafe or manual type conversions (in Go 1 at least). – Tejas Manohar Jan 31 '17 at 22:44

  • concreteCat, _ := cat.Interface().(Cat) is worked for me instead of reflect.ValueOf(cat).Interface().(Cat) – yountae.kang Aug 10 '18 at 3:01

  • @yountae.kang I'm not sure you found out why that happens, but either way the reason why cat.Interface().(Cat) works for you is because in the above use case cat is of type reflect.Value and there is no need to convert it to the reflect.Value type again. – hbn1991 Feb 20 '19 at 14:38

add a comment

2

 

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

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())
    }
}

share  improve this answer  follow 

answered Jan 2 at 18:13

 

rribas

25711 gold badge44 silver badges66 bronze badges

add a comment

0

 

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 < v.NumField(); i += 1 {
        field := v.Field(i)
        fieldType := field.Type()
        // out = append(out, field.Interface().(reflect.PtrTo(fieldType)))
        switch (fieldType.Name()) {
        case "int64":
            out = append(out, field.Interface().(int64))
            break`enter code here`
        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
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值