lianggo
lianggo

Reputation: 645

In Go, which value’s kind is 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?

Upvotes: 21

Views: 7452

Answers (7)

dolmen
dolmen

Reputation: 8716

You can not get directly the type of an interface{} value, but you can go through a pointer indirection (asking for the type of *interface{} and then asking the pointed type):

reflect.TypeOf((*interface{})(nil)).Elem()

Going through a slice type is the same mental exercise (asking for the type of []interface{} and then asking the slice element type):

reflect.TypeOf([]interface{}(nil)).Elem()

Go 1.22 added reflect.TypeFor which makes it much simpler:

reflect.TypeFor[interface{}]()
reflect.TypeFor[any]()          // any is a type alias for interface{}

Run this on play.golang.org:

t := reflect.TypeOf((*interface{})(nil)).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

Upvotes: 6

Nick Craig-Wood
Nick Craig-Wood

Reputation: 54117

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.

Upvotes: 3

WALID BELRHALMIA
WALID BELRHALMIA

Reputation: 441

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

Upvotes: -1

newacct
newacct

Reputation: 122518

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.

Upvotes: 3

Gustavo Niemeyer
Gustavo Niemeyer

Reputation: 23001

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.

Upvotes: 9

joshlf
joshlf

Reputation: 23637

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.

Upvotes: 13

Mostafa
Mostafa

Reputation: 28126

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.

Upvotes: 6

Related Questions