是否可以存储Go类型?

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

Is it possible to store a Go type

问题

我有一些接口和任意实现这些接口的结构体。我想要存储一个类型的数组,并能够遍历它们以查看哪些接口被实现了。是否可以存储这样的类型?我花了一些时间研究了反射包,但没有找到我想要的东西,如果这不是最佳实践的话,我可以理解。我想要做类似于这样的事情...而不是使用一个庞大的类型开关、fallthrough或者if..if...if。

type InterOne interface {
    InterOneMethod() string
}

var interfaceMap = map[string]interface{}{
    "One": InterOne,
    ...
}

func doesHandle(any interface{}) []string {
    var handles []string
    for k, v := range interfaceMap {
        if _, ok := any.(v); ok {
            handles = append(handles, k)
        }
    }
    return handles
}

编辑:被标记为正确答案的回答在技术上是正确的。但是由于关于方法调用和反射的过度使用的评论,我发现这种方法是不好的。相反,我使用了类型开关来检查单个接口,因为类型开关不支持fallthrough,并且使用了大量的if..if...if..来进行类型断言以进行适当的调用。

英文:

I've got a handful of interfaces, and n number of structs that arbitrarily implement these interfaces. I'd like to keep an array of types and be able to run a loop over them to see which ones are implemented. Is it possible to store a type like this? I spent a little bit of time with the reflect package, but couldn't really find what I was looking for, I understand if maybe this isn't best practice. Trying to do something similar to this.. without a giant type switch, fallthrough, or if.. if... if.

type InterOne interface {
    InterOneMethod() string
}

var interfaceMap = map[string]type {
    "One": InterOne,
    ...
}

func doesHandle(any interface{}) []string {
    var handles []string
    for k, v := range interfaceMap {
      if _, ok := any.(v); ok {
          handles = append(handles, k)
      }
    }
    return handles
}

EDIT: The answer marked as correct is technically right. I found that due to the comment about the method calling & the overuse of reflection, that this approach was a bad idea. Instead I went with a type switch to check for a single interface because fallthrough is not supported on type switch, and a large if.. if.. if.. with type assertions to be able to make the appropriate calls.

答案1

得分: 2

你可以使用反射(reflect)包,注意获取接口类型的唯一方法是使用 reflect.TypeOf((*INTERFACE)(nil)).Elem(),下面是一个可行的示例:

var interfaceMap = map[string]reflect.Type{
    "One": reflect.TypeOf((*InterOne)(nil)).Elem(),
    // ...
}

func doesHandle(any interface{}) []string {
    t := reflect.TypeOf(any)
    var handles []string
    for k, v := range interfaceMap {
        if t.Implements(v) {
            handles = append(handles, k)
        }
    }
    return handles
}

playground

英文:

You can use reflect, notice that to get the type of an interface the only way is to use reflect.TypeOf((*INTERFACE)(nil)).Elem(), here's a working example:

var interfaceMap = map[string]reflect.Type{
	"One": reflect.TypeOf((*InterOne)(nil)).Elem(),
....
}

func doesHandle(any interface{}) []string {
	t := reflect.TypeOf(any)
	var handles []string
	for k, v := range interfaceMap {
		if t.Implements(v) {
			handles = append(handles, k)
		}
	}
	return handles
}

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2016年4月18日 10:42:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/36684651.html
匿名

发表评论

匿名网友

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

确定