15
j:=1

Kindofjreflect.Int,正如预期的那样。

var j interface{} = 1

Kindj也是reflect.Int

哪种值的种类是reflect.Interface

4

7 回答 7

9

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

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

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

感谢这篇文章

于 2013-08-19T14:25:25.880 回答
7

到目前为止,答案似乎令人惊讶地令人费解,而问题及其回答实际上很简单:reflect.Interface 是一种接口值。

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

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

请注意,ValueOf(v)这不起作用,因为您想要 v 本身的类型,而不是它的内容。

于 2013-08-19T23:32:36.390 回答
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。(你可以在这里运行它。

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

因此,您可以看到您的问题“哪个值的种类是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。(这个在这里。)重点在 function Elem,它返回地图元素的类型,这里是接口类型。Elem也适用于指针、数组、切片和通道。有类似的函数用于获取映射键的类型(Key)、结构的字段(Field和朋友)以及函数的参数和返回参数(InOut)。您可以期望从所有这些中获得种类接口的类型。

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

于 2013-08-19T07:12:23.183 回答
3

我认为您的问题相当于:一个接口可以包含另一个接口吗?

反射定律中,我们发现了这一点

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

或者更详细

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

所以一个接口不能包含另一个接口。这意味着不存在这样的vreflect.TypeOf(v).Kind()is reflect.Interface。我猜你可能可以创建一个不安全的,但我认为你不会正常看到一个。

于 2013-08-19T07:14:04.980 回答
2

这取决于您所说的“价值”和“价值的种类”是什么意思。

在 Go 中,“类型”有不同的含义: -表达式的静态类型(编译时类型)。语言中的每个表达式都有一个在编译时已知的静态类型。- 接口值的动态类型(运行时类型)。接口类型的变量或表达式的特殊之处在于它可以保存不同类型的值,并且该底层值的类型在编译时是未知的。可以在运行时检查此运行时值及其类型。

反射发生在运行时,因此只需要询问接口值的动态类型。因此,您必须谈论接口值的基础值的类型。

nil接口值基本上是底层值和类型的“包装器”。请注意,此基础类型不能是接口类型。即包装器不能“包装”另一个包装器。这就是 joshlf13 的回答。这是因为当您从一种接口类型分配给另一种接口类型时,只会传输基础值。不记得它来自的接口类型。因此,不可能创建底层类型为接口类型的接口值。

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

因此,如果您的问题是:什么v可以reflect.ValueOf(v).Kind()评估为Interface; 答案是什么。这是因为,如果vis not nil,则ValueOf()获取其基础值的表示,该表示必须是非接口类型。如果vnil,那么根据 的文档reflect.ValueOf(),它返回类型的零值Value,并且该类型的文档Value.Kind()说调用Kind()零值返回Invalid

于 2013-08-20T10:45:36.563 回答
2

您不能直接获取interface{}值的类型,但可以通过指针间接获取:

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

在 play.golang.org 上运行:

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)

输出:

Type: interface {}
Kind: interface
IsInterface: true
于 2018-01-22T13:51:33.173 回答
-1

我会对此做出明确的回答。

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

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 总是得到一个宽泛的接口,我告诉过你的接口永远不会持有另一个接口。valueOf 不会采用 f 接口,但它会采用一个包含 s 结构的空接口。就像我们获取 f 的底层值并分配给一个空接口并传递给 ValueOf 方法

于 2015-09-27T00:03:27.890 回答