j:=1
正如预期的那样,Kind
的{{1}}为j
。
reflect.Int
var j interface{} = 1
的{p> Kind
也是j
。
哪种值是reflect.Int
?
答案 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
也无法获得传递给TypeOf
和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
。 (This one is here.)这一点在函数Elem
中,它返回一个映射元素的类型,这里是一个接口类型。 Elem
也适用于指针,数组,切片和通道。获取地图键(Key
)的类型,结构的字段(Field
和朋友)以及函数的参数和返回参数(In
和{{1}有类似的功能})。您可以期望从所有这些中获得类型的接口。
Rob Pike撰写了一篇很棒的文章The Laws of Reflection,它很好地解释了界面和反射。
答案 3 :(得分:3)
我认为您的问题等同于:接口是否可以包含其他接口?
在The Laws of Reflection我们找到了这个
接口变量可以存储任何具体(非接口)值
或者更详细
接口类型的变量存储一对:具体值 分配给变量,以及该值的类型描述符。更多 确切地说,值是底层的具体数据项 实现接口,类型描述了它的完整类型 项目
因此接口不能包含其他接口。这意味着没有值v
,reflect.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()
将获得其基础值的表示,该值必须是非接口类型。如果v
是nil
,那么通过reflect.ValueOf()
的文档,它会返回Value
类型的零值以及Value.Kind()
类型的文档说在零值上调用Kind()
会返回Invalid
。
答案 5 :(得分:2)
您无法直接获取lcov.info
值的类型,但您可以通过指针间接查找:
interface{}
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方法