Alex
Alex

Reputation: 36101

How to cast reflect.Value to its type?

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!

Upvotes: 75

Views: 104602

Answers (4)

elydelacruz
elydelacruz

Reputation: 155

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
}

Cheers!

Upvotes: 3

rribas
rribas

Reputation: 415

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

Upvotes: 5

sharewind
sharewind

Reputation: 2419

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)

Upvotes: 93

Alex
Alex

Reputation: 36101

Ok, I found it

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

Upvotes: 45

Related Questions