在Go中,哪种价值反映出来。接口?

时间:2013-08-19 03:52:09

标签: reflection go

j:=1
正如预期的那样,Kind的{​​{1}}为j

reflect.Int
var j interface{} = 1 的{​​p> Kind也是j

哪种值是reflect.Int

7 个答案:

答案 0 :(得分:8)

如果您正在寻找实用的解决方案,答案很简单,也很烦人。 reflect.TypeOf采用一种空接口类型,您可以将要传递的任何数据放入其中。这样做的问题是接口类型不能容纳另一种接口类型,这意味着您实际上无法将接口传递给reflect.TypeOf。有一个解决方法,但它有点痛苦。您需要做的是创建一个复合类型(如结构或切片或映射),其中一个元素类型是接口类型,并提取它。例如:

var sliceOfEmptyInterface []interface{}
var emptyInterfaceType = reflect.TypeOf(sliceOfEmptyInterface).Elem()

首先创建reflect.Type []interface{}的{​​{1}}表示形式(interface{}类型的切片),然后提取元素类型interface{}

this post提供。

答案 1 :(得分:7)

到目前为止,答案看起来令人惊讶地复杂,当问题及其响应实际上是直截了当时:reflect.Interface是一种接口值。

您可以通过以下方式轻松查看:

var v interface{}
var t = reflect.ValueOf(&v).Type().Elem()
fmt.Println(t.Kind() == reflect.Interface)

请注意,ValueOf(v)无效,因为您需要v本身的类型,而不是其内容。

答案 2 :(得分:5)

好问题。我花了将近一个小时才找到自己!

让我们从这段代码开始:

package main

import (
        "fmt"
        "reflect"
)

// define an interface
type Doer interface {
        Do()
}

// define a type that implements the interface
type T struct{}

func (T) Do() {}

func main() {
        var v Doer = T{}
        fmt.Println(reflect.TypeOf(v).Kind())
}

输出为struct,而不是interface。 (You can run it here.

这是因为即使我们将v定义为接口变量,此变量保持的实际的类型为T。它被称为变量的“动态类型”。包reflect的一个要点是帮助确定接口变量的动态类型,因此它为您提供动态类型,而不是接口。 (即使它想要,包reflect也无法获得传递给TypeOfValueOf的变量接口,因为变量作为值传递给函数。)

所以,你可以看到你的问题,“哪种价值是Interface?”,在技术上可以用“没有”来回答。

那么Interface有什么用呢?看到这段代码:

// assuming the above code, just with this main function
func main() {
        a := make([]Doer, 0)
        fmt.Println(reflect.TypeOf(a).Elem().Kind())
}

这会打印interface。 (This one is here.)这一点在函数Elem中,它返回一个映射元素的类型,这里是一个接口类型。 Elem也适用于指针,数组,切片和通道。获取地图键(Key)的类型,结构的字段(Field和朋友)以及函数的参数和返回参数(In和{{1}有类似的功能})。您可以期望从所有这些中获得类型的接口。

Rob Pike撰写了一篇很棒的文章The Laws of Reflection,它很好地解释了界面和反射。

答案 3 :(得分:3)

我认为您的问题等同于:接口是否可以包含其他接口?

The Laws of Reflection我们找到了这个

  

接口变量可以存储任何具体(非接口)值

或者更详细

  

接口类型的变量存储一对:具体值   分配给变量,以及该值的类型描述符。更多   确切地说,值是底层的具体数据项   实现接口,类型描述了它的完整类型   项目

因此接口不能包含其他接口。这意味着没有值vreflect.TypeOf(v).Kind()reflect.Interface。我想你可能会创建一个不安全的,但我认为你不会正常看到它。

答案 4 :(得分:2)

这取决于你的意思"价值"和"价值"。

在Go中,"输入"可以表示不同的事情:   - 表达式的 static 类型(编译时类型)。语言中的每个表达式都有一个在编译时已知的静态类型。   - 接口值的动态类型(运行时类型)。接口类型的变量或表达式是特殊的,因为它可以保存不同类型的值,并且在编译时不知道该基础值的类型。可以在运行时检查此运行时值及其类型。

反射在运行时发生,因此询问接口值的动态类型是很有趣的。因此,您必须讨论接口值的基础值的类型。

nil接口值基本上是"包装器"围绕基础价值和类型。请注意,此基础类型不能是接口类型。即包装不能包装"另一个包装器。这就是joshlf13的答案所说的。这是因为从一种接口类型分配到另一种接口类型时,只传输基础值。它来自的接口类型不会被记住。因此,不可能创建其底层类型是接口类型的接口值。

reflect.ValueOf()reflect.TypeOf()这样的反射函数允许您传入接口值并获取基础值的表示。参数类型为interface{},因为这是允许您传入任何内容的类型。但是,他们假设您实际上对该接口值的基础值感兴趣,您可以通过首先传递它来转换为interface{},或者从其他地方获取它并想要检查它。因此,反射函数基本上用于检查接口的基础值(如上所述,必须是非接口类型),而不是实际的接口类型参数。

因此,如果您的问题是:v可以使reflect.ValueOf(v).Kind()评估为Interface;答案一无所获。这是因为,如果v不是nil,那么ValueOf()将获得其基础值的表示,该值必须是非接口类型。如果vnil,那么通过reflect.ValueOf()的文档,它会返回Value类型的零值以及Value.Kind()类型的文档说在零值上调用Kind()会返回Invalid

答案 5 :(得分:2)

您无法直接获取lcov.info值的类型,但您可以通过指针间接查找:

interface{}

运行此on play.golang.org

reflect.TypeOf(new(interface{})).Elem()

输出:

t := reflect.TypeOf(new(interface{})).Elem()
fmt.Printf("Type: %s\n", t)
fmt.Printf("Kind: %v\n", t.Kind())
fmt.Printf("IsInterface: %v\n", t.Kind() == reflect.Interface)

答案 6 :(得分:-1)

我会为此做出明确答案。

首先你必须现在接口可以容纳除了另一个接口之外的任何东西。所以,让我们说清楚。看看这个程序。

type i interface {
  hello()
 }
 type s struct{
 name string
 }
 func (a s)hello(){} 
 func main(){
  var f i //here we create an empty interface i
  f=s{} //now f hold a structure of type s
  fmt.Print(reflect.ValueOf(f).Kind())   // here we got a structure type so what really happen now i will explained  
  }

ValueOf方法的签名是:

 reflect.ValueOf(i interface{}) 

所以ValueOf总是得到一个ampty接口,我告诉你接口永远不会拥有另一个接口。 valueOf不会占用f接口,但它会采用一个保持s结构的空接口。它就像我们删除f的基础值并分配给一个空接口并传递给ValueOf方法