【问题标题】:Is it possible to store a Go type是否可以存储 Go 类型
【发布时间】:2016-04-19 01:39:41
【问题描述】:

我有一些接口,以及任意实现这些接口的 n 个结构。我想保留一个类型的数组,并能够在它们上运行一个循环来查看实现了哪些类型。是否可以存储这样的类型?我在反射包上花了一点时间,但找不到我想要的东西,我知道这可能不是最佳实践。尝试做与此类似的事情.. 没有巨大的类型开关、失败或 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
}

编辑:标记为正确的答案在技术上是正确的。我发现由于对方法调用和过度使用反射的评论,这种方法是一个坏主意。相反,我使用类型切换来检查单个接口,因为类型切换不支持失败,以及带有类型断言的大型 if.. if.. if.. 以便能够进行适当的调用。

【问题讨论】:

  • 不知道你为什么要做这样的事情,但如果你不打算在其他地方重用interfaceMap,那么一堆ifs 可能是一种更简单的实现方式这个:play.golang.org/p/eSUf2xSqI7.
  • 不确定我是否真的会重复使用它,这只是我目标的一个例子。

标签: go go-interface


【解决方案1】:

你可以使用反射,注意获取接口类型的唯一方法是使用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

【讨论】:

  • 这看起来和我想要的完全一样,reflect.TypeOf((*InterOne)(nil)) 和 reflect.TypeOf((*InterOne)(nil)).Elem() 有什么区别,两者都是反射。类型对吗?
  • 是否也可以在任何设备上调用 InterOneMethod?通常我会先做一个类型断言。
  • reflect.TypeOf((*InterOne)(nil)) 返回一个指向接口的指针,这几乎是无效的。您可以使用 reflect.ValuOf(any).MethodByName 调用 InterOneMethod,但调用这样的函数非常慢。
猜你喜欢
  • 1970-01-01
  • 2016-06-19
  • 2014-05-05
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 2012-10-18
相关资源
最近更新 更多