j:=1
Kind
ofj
是reflect.Int
,正如预期的那样。
var j interface{} = 1
Kind
的j
也是reflect.Int
。
哪种值的种类是reflect.Interface
?
j:=1
Kind
ofj
是reflect.Int
,正如预期的那样。
var j interface{} = 1
Kind
的j
也是reflect.Int
。
哪种值的种类是reflect.Interface
?
如果您正在寻找一个实用的解决方案,答案是简单而烦人的。reflect.TypeOf
采用一个空接口类型,您可以在其中放入您想要传递的任何数据。这样做的问题是接口类型不能保存另一个接口类型,这意味着您实际上无法将接口传递给reflect.TypeOf
. 有一个解决方法,但它有点痛苦。您要做的是创建一个复合类型(如结构或切片或映射),其中元素类型之一是接口类型,然后提取它。例如:
var sliceOfEmptyInterface []interface{}
var emptyInterfaceType = reflect.TypeOf(sliceOfEmptyInterface).Elem()
这首先创建(类型切片)的reflect.Type
表示,然后提取元素类型,即.[]interface{}
interface{}
interface{}
感谢这篇文章。
到目前为止,答案似乎令人惊讶地令人费解,而问题及其回答实际上很简单:reflect.Interface 是一种接口值。
您可以通过以下方式轻松看到:
var v interface{}
var t = reflect.ValueOf(&v).Type().Elem()
fmt.Println(t.Kind() == reflect.Interface)
请注意,ValueOf(v)
这不起作用,因为您想要 v 本身的类型,而不是它的内容。
好问题。我花了将近一个小时才发现自己!
让我们从这段代码开始:
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
也无法获得传递给TypeOf
and的变量接口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
和朋友)以及函数的参数和返回参数(In
和Out
)。您可以期望从所有这些中获得种类接口的类型。
Rob Pike 写了一篇很棒的文章The Laws of Reflection,很好地解释了接口和反射。
我认为您的问题相当于:一个接口可以包含另一个接口吗?
在反射定律中,我们发现了这一点
接口变量可以存储任何具体(非接口)值
或者更详细
接口类型的变量存储一对:分配给变量的具体值,以及该值的类型描述符。更准确地说,值是实现接口的底层具体数据项,类型描述了该项的完整类型。
所以一个接口不能包含另一个接口。这意味着不存在这样的v
值reflect.TypeOf(v).Kind()
is reflect.Interface
。我猜你可能可以创建一个不安全的,但我认为你不会正常看到一个。
这取决于您所说的“价值”和“价值的种类”是什么意思。
在 Go 中,“类型”有不同的含义: -表达式的静态类型(编译时类型)。语言中的每个表达式都有一个在编译时已知的静态类型。- 接口值的动态类型(运行时类型)。接口类型的变量或表达式的特殊之处在于它可以保存不同类型的值,并且该底层值的类型在编译时是未知的。可以在运行时检查此运行时值及其类型。
反射发生在运行时,因此只需要询问接口值的动态类型。因此,您必须谈论接口值的基础值的类型。
非nil
接口值基本上是底层值和类型的“包装器”。请注意,此基础类型不能是接口类型。即包装器不能“包装”另一个包装器。这就是 joshlf13 的回答。这是因为当您从一种接口类型分配给另一种接口类型时,只会传输基础值。不记得它来自的接口类型。因此,不可能创建底层类型为接口类型的接口值。
反射函数就像reflect.ValueOf()
andreflect.TypeOf()
让你传入一个接口值并获得底层值的表示。参数类型是interface{}
因为它是允许您传入任何内容的类型。但是,他们假设您实际上对该接口值的底层值感兴趣,您可以interface{}
通过首先传递它来转换它,或者您从其他地方获取它并想要检查它。因此,反射函数基本上是用于检查接口的底层值(如上所述,它必须是非接口类型),而不是实际的接口类型参数。
因此,如果您的问题是:什么v
可以reflect.ValueOf(v).Kind()
评估为Interface
; 答案是什么。这是因为,如果v
is not nil
,则ValueOf()
获取其基础值的表示,该表示必须是非接口类型。如果v
是nil
,那么根据 的文档reflect.ValueOf()
,它返回类型的零值Value
,并且该类型的文档Value.Kind()
说调用Kind()
零值返回Invalid
。
您不能直接获取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)
输出:
Type: interface {}
Kind: interface
IsInterface: true
我会对此做出明确的回答。
首先你必须现在 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 方法