Owen Allen
Owen Allen

Reputation: 11958

How do you get struct value on unknown interface{}

If I have a struct and I want to get it's key, but it's currently of type interface{} how do I do that?

Currently I get the following compilation error:

invalid operation: d[label] (index of type interface {})

Play: http://play.golang.org/p/PLr91d55GX

package main

import "fmt"
import "reflect"

type Test struct {
    s string
}

func main() {
    test := Test{s: "blah"}
    fmt.Println(getProp(test, "s"))
}

func getProp(d interface{}, label string) (interface{}, bool) {
    switch reflect.TypeOf(d).Kind() {
    case reflect.Struct:
        _, ok := reflect.TypeOf(d).FieldByName(label)
        if ok {
                    // errors here because interface{} doesn't have index of type 
            return d[label], true
        } else {
            return nil, false
        }
    }
}

Do I really have to do the massive case statement on each different type and call the reflected reflect.ValueOf(x).String() etc? I'm hoping there is a more elegant way.

Upvotes: 2

Views: 4105

Answers (2)

Derek
Derek

Reputation: 3137

I'm not sure exactly what you're looking for, but there is a slightly simpler way to look for interface{} types. In your case, you could use:

switch val := d.(type) {
  case Test:
    fmt.Println(d.s)
}

Obviously, I'm not doing the same thing as you were, but the idea is that you can check the type with "d.(type)", and once "case Test:" determines that it is a struct of your Test type, you can access it as such.

Unfortunately, this doesn't address the accessing of the value within the struct by the label, but it at least is a more elegant way of determining the type, and @nos shows how to do that with

v := reflect.ValueOf(d).FieldByName(label)
return v.Interface(), true

Upvotes: 0

nos
nos

Reputation: 229098

You could do this, however I think it'll only work if your struct member s was an exported field (i.e. use a capital S in your example)

func getProp(d interface{}, label string) (interface{}, bool) {
    switch reflect.TypeOf(d).Kind() {
    case reflect.Struct:
        v := reflect.ValueOf(d).FieldByName(label)
             return v.Interface(), true
    }
   return nil, false
}

(+ some more error handling)

Upvotes: 2

Related Questions