英文:
In Go, which value’s kind is reflect.Interface?
问题
j
的类型是reflect.Int
,符合预期。
var j interface{} = 1
中,j
的类型仍然是reflect.Int
。
哪个值的类型是reflect.Interface
?
英文:
j:=1
Kind
of j
is reflect.Int
, as expected.
var j interface{} = 1
Kind
of j
is also reflect.Int
.
Which value’s kind is reflect.Interface
?
答案1
得分: 12
如果你正在寻找一个实用的解决方案,答案很简单但有点烦人。reflect.TypeOf
接受一个空接口类型,你可以将任何你想传递的数据放入其中。但问题是,一个接口类型无法容纳另一个接口类型,这意味着你实际上无法将接口传递给 reflect.TypeOf
。有一个变通方法,但有点繁琐。你需要创建一个复合类型(比如结构体、切片或映射),其中一个元素类型是接口类型,并提取它。例如:
var sliceOfEmptyInterface []interface{}
var emptyInterfaceType = reflect.TypeOf(sliceOfEmptyInterface).Elem()
这首先创建了 []interface{}
(一个 interface{}
类型的切片)的 reflect.Type
表示,然后提取了元素类型 interface{}
。
参考自这篇帖子。
英文:
If you're looking for a practical solution, the answer is simple and annoying. reflect.TypeOf
takes an empty interface type into which you put whatever data you want to pass. The problem with this is that an interface type can't hold another interface type, which means that you effectively can't pass an interface to reflect.TypeOf
. There is a workaround, but it's a bit painful. What you have to do is make a composite type (like a struct or slice or map) where one of the element types is an interface type, and extract it. For example:
var sliceOfEmptyInterface []interface{}
var emptyInterfaceType = reflect.TypeOf(sliceOfEmptyInterface).Elem()
That first creates a reflect.Type
representation of []interface{}
(a slice of interface{}
types) and then extracts the element type, which is interface{}
.
Courtesy of this post.
答案2
得分: 9
到目前为止,答案似乎令人惊讶地复杂,而问题及其回答实际上是直接的:reflect.Interface 是接口值的类型。
你可以通过以下方式轻松地看到这一点:
var v interface{}
var t = reflect.ValueOf(&v).Type().Elem()
fmt.Println(t.Kind() == reflect.Interface)
请注意,ValueOf(v)
不起作用,因为你想要的是 v 本身的类型,而不是它的内容。
英文:
The answers so far seem surprisingly convoluted, when the question and its response is in fact straightforward: reflect.Interface is the kind of interface values.
You can easily see that with:
var v interface{}
var t = reflect.ValueOf(&v).Type().Elem()
fmt.Println(t.Kind() == reflect.Interface)
Note that ValueOf(v)
would not work because you want the type of v itself, not its content.
答案3
得分: 6
好的,以下是翻译好的内容:
很好的问题。我花了将近一个小时的时间来找到答案!
让我们从这段代码开始:
package main
import (
"fmt"
"reflect"
)
// 定义一个接口
type Doer interface {
Do()
}
// 定义一个实现接口的类型
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
和 ValueOf
的变量的接口,因为变量作为值传递给函数。)
因此,你可以看到你的问题,“哪个值的类型是 Interface
?”,从技术上讲可以回答为“没有值”。
那么,Interface
有什么用呢?看看下面的代码:
// 假设上面的代码,只有这个 main 函数
func main() {
a := make([]Doer, 0)
fmt.Println(reflect.TypeOf(a).Elem().Kind())
}
这将打印出 interface
。(这里有代码)关键在于 Elem
函数,它返回一个映射的元素类型,这里是一个接口类型。Elem
也适用于指针、数组、切片和通道。类似的函数用于获取映射的键的类型(Key
)、结构体的字段类型(Field
和相关函数)以及函数的参数和返回值类型(In
和 Out
)。你可以期望从所有这些函数中获得接口类型的类型。
Rob Pike 写了一篇很棒的文章,The Laws of Reflection,非常好地解释了接口和反射。
英文:
Good question. I worked on it for almost an hour to find out myself!
Let’s start with this code:
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())
}
The output is struct
, not interface
. (You can run it here.)
That’s because even though we define v
as an interface variable, the actual value this variable holds is of type T
. It’s called “dynamic type” of the variable. One of the main points of package reflect
is to help determine the dynamic type of interface variables, so it gives you the dynamic type, not the interface. (And even if it wanted to, package reflect
couldn’t get the interface of variables passed to TypeOf
and ValueOf
, because variables are passed as values to functions.)
So, you can see that your question, “which value’s kind is Interface
?”, can technically be answered with “no value”.
But what that Interface
is good for, then? See this code:
// assuming the above code, just with this main function
func main() {
a := make([]Doer, 0)
fmt.Println(reflect.TypeOf(a).Elem().Kind())
}
This prints interface
. (This one is here.) The point is in function Elem
, which returns type of a map’s elements, an interface type here. Elem
also works on pointers, arrays, slices, and channels. There are similar function for getting type of a map’s key (Key
), a struct’s fields (Field
and friends), and a function’s arguments and return parameter (In
and Out
). You can expect to get types of kind interface from all of these.
Rob Pike wrote an awesome article, The Laws of Reflection, that explains interfaces and reflection very well.
答案4
得分: 5
你可以通过指针间接地获取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
英文:
You can not get directly the type of an interface{}
value, but you can go through a pointer indirection:
reflect.TypeOf(new(interface{})).Elem()
Run this on 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)
Output:
Type: interface {}
Kind: interface
IsInterface: true
答案5
得分: 3
我认为你的问题等同于:一个接口可以包含另一个接口吗?
在《反射定律》(The Laws of Reflection)中,我们可以找到以下内容:
一个接口变量可以存储任何具体(非接口)值。
或者更详细地说:
接口类型的变量存储了一对值:分配给变量的具体值和该值的类型描述符。更准确地说,该值是实现接口的底层具体数据项,而类型描述了该项的完整类型。
因此,一个接口不能包含另一个接口。这意味着不存在一个值 v
,使得 reflect.TypeOf(v).Kind()
是 reflect.Interface
。我猜你也许可以使用 unsafe
创建一个这样的值,但我认为在正常情况下你不会遇到这种情况。
英文:
I think your question is equivalent to: Can an interface contain another interface?
In The Laws of Reflection we find this
> An interface variable can store any concrete (non-interface) value
Or in more detail
> A variable of interface type stores a pair: the concrete value
> assigned to the variable, and that value's type descriptor. To be more
> precise, the value is the underlying concrete data item that
> implements the interface and the type describes the full type of that
> item.
So an interface can't contain another interface. This means that there isn't a value v
such that reflect.TypeOf(v).Kind()
is reflect.Interface
. I guess you might be able to create one with unsafe but I don't think you'll ever see one normally.
答案6
得分: 2
这取决于你对“value”和“value's kind”所指的含义。
在Go语言中,“type”可以有不同的含义:
- 表达式的静态类型(编译时类型)。语言中的每个表达式在编译时都有一个已知的静态类型。
- 接口值的动态类型(运行时类型)。接口类型的变量或表达式是特殊的,它可以保存不同类型的值,并且这个底层值的类型在编译时是未知的。这个运行时值及其类型可以在运行时进行检查。
反射是在运行时发生的,所以只有询问接口值的动态类型才有意义。因此,你一定是在谈论接口值的底层值的类型。
非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
。
英文:
It depends on what you mean by "value" and "value's kind".
In Go, "type" can mean different things:
- The static type (compile-time type) of an expression. Every expression in the language has a static type known at compile time.
- The dynamic type (runtime type) of an interface value. A variable or expression of interface type is special in that it can hold values of different types, and the type of this underlying value is not known at compile-time. This runtime value and its type can be inspected at runtime.
Reflection happens at runtime, so it is only interesting to ask about the dynamic type of an interface value. Thus, you must be talking about the type of the underlying value of an interface value.
A non-nil
interface value is basically a "wrapper" around an underlying value and type. Note that this underlying type cannot be an interface type. i.e. the wrapper cannot "wrap" another wrapper. This is what joshlf13's answer is saying. This is because when you assign from one interface type to another interface type, only the underlying value is transferred. The interface type it came from is not remembered. Thus, it is impossible to create an interface value whose underlying type is an interface type.
Reflection functions like reflect.ValueOf()
and reflect.TypeOf()
let you pass in an interface value and get a representation of the underlying value. The parameter type is interface{}
because that is the type that allows you to pass in anything. However, they assume that you are actually interesting in the underlying value of that interface value, which you either turned into interface{}
by passing it in the first place, or you got it from somewhere else and want to examine it. Thus, reflection functions are fundamentally for examining the underlying value of interfaces (which, as explained above, must be of non-interface type), and not the actual interface type argument.
Therefore, if your question is: what v
can make reflect.ValueOf(v).Kind()
evaluate to Interface
; the answer is nothing. This is because, if v
is not nil
, then ValueOf()
gets a representation of its underlying value, which must be of non-interface type. And if v
is nil
, then by the documentation of reflect.ValueOf()
, it returns the zero value of the Value
type, and the documentation for the Value.Kind()
type says that calling Kind()
on the zero value returns Invalid
.
答案7
得分: -1
我会为这个进行清晰的回答。
首先,你必须知道接口可以持有任何类型,除了另一个接口。让我们来看看这个程序。
type i interface {
hello()
}
type s struct {
name string
}
func (a s) hello() {}
func main() {
var f i // 在这里我们创建了一个空接口 i
f = s{} // 现在 f 持有了一个类型为 s 的结构体
fmt.Print(reflect.ValueOf(f).Kind()) // 这里我们得到了一个结构体类型,所以现在发生了什么我会解释
}
ValueOf 方法的签名是:
reflect.ValueOf(i interface{})
所以 ValueOf 总是获取一个空接口,正如我之前告诉过你,接口不能持有另一个接口。所以 ValueOf 不会接受 f 接口,但它会接受一个持有 s 结构体的空接口。就好像我们获取了 f 的底层值并将其赋给一个空接口,然后将其传递给 ValueOf 方法。
英文:
i will make a clear answer for this .
first you have to now somthing interfaces can hold anything except another interface . so let's make that clear. take a look to this program.
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
}
the signature of ValueOf methode is :
reflect.ValueOf(i interface{})
so the ValueOf get always an ampty interface what i had told you interface never hold another interface so . valueOf will not take f interface but it wlli take an empty interface that hold s structure. it's like if we taked the underlying value of f and assigned to an empty interface and passed to ValueOf methode
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论