【问题标题】:How to get the reflect.Type of an interface?如何获取接口的reflect.Type?
【发布时间】:2011-10-31 06:18:53
【问题描述】:

为了确定给定类型是否使用反射包实现接口,您需要将反射.Type 传递给反射.Type.Implements()。您如何获得其中一种类型?

例如,尝试获取未初始化的error(接口)类型的类型工作(当您在其上调用 Kind() 时它会恐慌)

var err error
fmt.Printf("%#v\n", reflect.TypeOf(err).Kind())

【问题讨论】:

  • 这可能会有所帮助:stackoverflow.com/questions/6390585/…
  • 这个问题太老了,它指的是自 Go 1.0 以来不存在的接口 (os.Error)。
  • 我已经解决了将os.Error 替换为error 的问题。

标签: go


【解决方案1】:

这样做:

var err error
t := reflect.TypeOf(&err).Elem()

或者在一行中:

t := reflect.TypeOf((*error)(nil)).Elem()

【讨论】:

  • 恕我直言,如果要检查的类型是接口,则仅当接口方法在“裸”接收器上实现时才有效,而不是在指针接收器上实现,因此请注意这种情况。
  • @andig 不正确。如果我们谈论的是接口,而不是接口的实现,方法总是在接口类型本身上。永远不要在指向接口的指针上。 (实际上,如果你试图在指向接口的指针上调用接口方法,编译器会报错。)
【解决方案2】:

Even Shaws 的回答是正确的,但很简短。 reflect.TypeOf 方法文档中的更多详细信息:

// As interface types are only used for static typing, a common idiom to find
// the reflection Type for an interface type Foo is to use a *Foo value.

writerType := reflect.TypeOf((*io.Writer)(nil)).Elem()

fileType := reflect.TypeOf((*os.File)(nil)).Elem()
fmt.Println(fileType.Implements(writerType))

【讨论】:

  • reflect.TypeOf((*interface{})(nil)).Elem()
  • @mh-cbon 我已经修复了丢失的.Elem()
【解决方案3】:

对于那里的谷歌用户,我刚刚遇到了可怕的scannable dest type interface {} with >1 columns (XX) in result 错误。

Evan Shaw 的回答对我不起作用。这是我解决它的方法。我也在使用lann/squirrel 库,但您可以轻松地将其取出。

解决方案真的没有那么复杂,只要知道要进行的反射调用的神奇组合即可。

me.GetSqlx() 函数只是返回一个实例给*sqlx.DB

    func (me *CommonRepo) Get(query sq.SelectBuilder, dest interface{}) error {
      sqlst, args, err := query.ToSql()
      if err != nil {
        return err
      }
      // Do some reflection magic so that Sqlx doesn't hork on interface{}
      v := reflect.ValueOf(dest)
      return me.GetSqlx().Get(v.Interface(), sqlst, args...)
    }
    func (me *CommonRepo) Select(query sq.SelectBuilder, dest interface{}) error {
      sqlst, args, err := query.ToSql()
      if err != nil {
        return err
      }
      // Do some reflection magic so that Sqlx doesn't hork on interface{}
      v := reflect.ValueOf(dest)
      return me.GetSqlx().Select(v.Interface(), sqlst, args...)
    }

然后调用它你可以这样做:

    func (me *myCustomerRepo) Get(query sq.SelectBuilder) (rec Customer, err error) {
      err = me.CommonRepo.Get(query, &rec)
      return
    }
    func (me *myCustomerRepo) Select(query sq.SelectBuilder) (recs []Customer, err error) {
      err = me.CommonRepo.Select(query, &recs)
      return
    }

这使您可以在所有地方都拥有强类型,但在一个地方拥有所有通用逻辑(本例中为CommonRepo)。

【讨论】:

  • 首先,me(或 thisself)不是好的接收者名称(即使在需要其中之一的语言中);惯用的 Go 使用适合类型的接收器名称。其次,确定v := reflect.ValueOf(dest); x := v.Interface()just a round about way of doing x := dest? (或者 var x interface{} = dest 如果 dest 还不是 interface{} 类型)。
  • 针对单个公司(无论公司有多大)的人的答案在这里无关紧要。
  • @dolmen 很确定他们只是指人们在谷歌上搜索,而不是在谷歌工作的人。
猜你喜欢
  • 2011-04-03
  • 2016-09-24
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 2023-01-19
  • 2011-09-08
相关资源
最近更新 更多