如何在未知的interface{}上获取struct值

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

How do you get struct value on unknown interface{}

问题

如果我有一个结构体,并且我想要获取它的键,但它当前的类型是interface{},我该如何做到这一点?

目前我得到以下编译错误:

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 {
            // 这里出错,因为interface{}没有类型的索引
            return d.(Test).s, true
        } else {
            return nil, false
        }
    }
}

我真的需要在每个不同的类型上进行大量的case语句,并调用反射的reflect.ValueOf(x).String()等吗?我希望有一种更优雅的方式。

英文:

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.

答案1

得分: 2

你可以这样做,但是我认为只有在你的结构体成员s是一个导出字段时才能起作用(即在你的示例中使用大写的S

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
}

(+一些更多的错误处理)

英文:

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)

答案2

得分: 0

我不确定你具体在寻找什么,但是有一种稍微简单的方法可以查找interface{}类型。在你的情况下,你可以使用:

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

显然,我并没有做和你一样的事情,但是这个想法是你可以使用"d.(type)"来检查类型,一旦"case Test:"确定它是你的Test类型的结构体,你就可以像这样访问它。

不幸的是,这并没有解决通过标签访问结构体内部值的问题,但至少这是一种更优雅的确定类型的方式,@nos展示了如何使用

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

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

huangapple
  • 本文由 发表于 2012年12月13日 17:15:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/13856539.html
匿名

发表评论

匿名网友

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

确定