Get the reflect.Kind of a type which is based on a primitive type - go

I would like to get the reflect.Kind as a reflect.Interface for a type which implements an interface but where its implementation is based on a primitive type: type id string
An alternative answer for this could be how to get any kind of reflect.Type that returns reflect.Interfaces when calling Kind().
Here is a full example on the Go Playground:
type ID interface {
myid()
}
type id string
func (id) myid() {}
func main() {
id := ID(id("test"))
fmt.Println(id)
fmt.Println(reflect.TypeOf(id))
// How to get the kind to return "reflect.Interface" from the var "id"?
fmt.Println(reflect.TypeOf(id).Kind())
}

reflect.TypeOf() (and reflect.ValueOf()) expects an interface{}. Basically whatever value you pass to reflect.TypeOf(), if it's not already an interface value, it will be wrapped in an interface{} implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed as a interface{}.
In order to avoid this "repacking", this is one of those rare cases when a pointer to interface makes sense, in fact you can't avoid it here. You have to pass a pointer to the interface value.
So if you pass a pointer to interface, this pointer will be wrapped in an interface{} value. You may use Type.Elem() to get the type descriptor of the "pointed type": that is, the element type of the pointer type, which will be the type descriptor of the interface type you're looking for.
Example:
id := ID(id("test"))
fmt.Println(id)
t := reflect.TypeOf(&id).Elem()
fmt.Println(t)
fmt.Println(t.Kind())
Which outputs (try it on the Go Playground):
test
main.ID
interface
See related question: What is the difference between reflect.ValueOf() and Value.Elem() in go?

Related

Object variables are passed into functions as interface types. Will there be implicit conversion [duplicate]

I would like to get the reflect.Kind as a reflect.Interface for a type which implements an interface but where its implementation is based on a primitive type: type id string
An alternative answer for this could be how to get any kind of reflect.Type that returns reflect.Interfaces when calling Kind().
Here is a full example on the Go Playground:
type ID interface {
myid()
}
type id string
func (id) myid() {}
func main() {
id := ID(id("test"))
fmt.Println(id)
fmt.Println(reflect.TypeOf(id))
// How to get the kind to return "reflect.Interface" from the var "id"?
fmt.Println(reflect.TypeOf(id).Kind())
}
reflect.TypeOf() (and reflect.ValueOf()) expects an interface{}. Basically whatever value you pass to reflect.TypeOf(), if it's not already an interface value, it will be wrapped in an interface{} implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed as a interface{}.
In order to avoid this "repacking", this is one of those rare cases when a pointer to interface makes sense, in fact you can't avoid it here. You have to pass a pointer to the interface value.
So if you pass a pointer to interface, this pointer will be wrapped in an interface{} value. You may use Type.Elem() to get the type descriptor of the "pointed type": that is, the element type of the pointer type, which will be the type descriptor of the interface type you're looking for.
Example:
id := ID(id("test"))
fmt.Println(id)
t := reflect.TypeOf(&id).Elem()
fmt.Println(t)
fmt.Println(t.Kind())
Which outputs (try it on the Go Playground):
test
main.ID
interface
See related question: What is the difference between reflect.ValueOf() and Value.Elem() in go?

get reflect.struct from interface

hi a have this func for get type of value, but i try this and never can get reflect.struct:
type Test struct {
Code int
Name string
}
func main(){
test := getTest()
data, err := getBytes(slice...)
sanitizedFile := bytes.Split(data, []byte("\r\n"))
err = Unmarshal(sanitizedFile[0], &test)
}
func getTest() interface{} {
return Test{}
}
With this code i don't can get the reflecet.struct from v params in Unmarshall func
func Unmarshal(data []byte, v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
rvElem := rv.Elem()
switch rvElem.Kind() {
case reflect.Struct:
// implement me
}
}
return ErrInvalid
}
I would like to know if I can somehow find out if an interface is of type struct or access the values ​​of that struct.
I think the real problem here is illustrated by this quote:
I would like to know if I can somehow find out if an interface is of type struct or access the values ​​of that struct.
An interface value isn't "of type struct". Never! An interface value can contain a value whose type is some structure, but it is not a value of that type. It just contains one. This is similar to the way that a box1 you get from Amazon can contain a corkscrew, but the box is not a corkscrew, ever.
Given a non-nil value of type interface I for some interface type I, you know that you have a value that implements the methods of I. Since {} is the empty set of methods, all types implement it, so given a (still non-nil) value of type interface{}, you have a value that implements no methods. That's not at all useful by itself: it means you can invoke no methods, which means you can't do anything method-like.
But just because you can't do anything method-y doesn't mean you can't do anything at all. Any interface value, regardless of the interface type, can have a type-assertion used on it:
iv := somethingThatReturnsAnInterface()
cv := iv.(struct S) // assert that iv contains a `struct S`
If iv does in fact contain a struct S value—if that's what's inside the box once you open it—then this type-assertion doesn't panic, and cv winds up with the concrete value of type struct S. If panic is undesirable, we can use the cv, ok := iv.(struct S) form, or a type switch. All of these—including the version that panics—work by checking the type of the value inside the interface.
What this—or, more precisely, the way the Go language is defined—tells us is that the interface "box" really holds two things:
a concrete type, and
a concrete value.
Well, that is, unless it holds a <nil, nil> pair, in which case iv == nil is true. Note that the iv == nil test actually tests both parts.
If Go had a syntax for this, we could write something like iv.type and iv.value to get at the two separate parts. But we can't do that. We have to use type assertions, type-switch, or reflect. So, going back to this:
I would like to know if I can somehow find out if an interface is of type struct
we can see that the question itself is just a little malformed. We don't want to know if an interface value has this type. We want to know if a non-nil interface's held value is of this type, as if we could inspect iv.type and iv.value directly.
If you have a limited set of possible types, you can use the type-switch construct, and enumerate all your allowed possiblities:
switch cv := iv.(type) {
case struct S:
// work with cv, which is a struct S
case *struct S:
// work with cv, which is a *struct S
// add more cases as appropriate
}
If you need more generality, instead of doing the above, we end up using the reflect package:
tv := reflect.TypeOf(iv)
or:
vv := reflect.ValueOf(iv)
The latter is actually the more useful form, since vv captures both the iv.type pseudo-field and the iv.value pseudo-field.
As mkopriva notes in a comment, test, in your sample code, has type interface{}, so &test has type *interface{}. In most cases this is not a good idea: you just want to pass the interface{} value directly.
To allow the called function to set the object to a new value, you will want to pass a pointer to the object as the interface value. You do not want to pass a pointer to the interface while having the interface hold the struct "in the box" as it were. You need a reflect.Value on which you can invoke Set(), and to get one, you will need to follow an elem on the reflect.Value that is a pointer to the struct (not one that is a pointer to the interface).
There's a more complete example here on the Go Playground.
1This is partly an allusion to "boxed values" in certain other programming languages (see What is boxing and unboxing and what are the trade offs?), but partly literal. Don't mistake Go's interfaces for Java's boxed values, though: they are not the same at all.
Maybe what you need is type assertion?
t, ok := v.(myStruct)
https://tour.golang.org/methods/15
In any case this code prints "struct":
type tt struct {}
var x tt
var z interface{}
z = x
v := reflect.ValueOf(z).Kind()
fmt.Printf("%v\n", v)
And see this for setting the value of a struct field using reflection:
Using reflect, how do you set the value of a struct field?

what does reflect.TypeOf((*error)(nil)).Elem()` mean?

func (s *service) registerMethods() {
s.method = make(map[string]*methodType)
for i := 0; i < s.typ.NumMethod(); i++ {
method := s.typ.Method(i)
mType := method.Type
if mType.NumIn() != 3 || mType.NumOut() != 1 {
continue
}
if mType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() {
continue
}
argType, replyType := mType.In(1), mType.In(2)
if !isExportedOrBuiltinType(argType) || !isExportedOrBuiltinType(replyType) {
continue
}
s.method[method.Name] = &methodType{
method: method,
ArgType: argType,
ReplyType: replyType,
}
log.Printf("rpc server: register %s.%s\n", s.name, method.Name)
}
}
what does reflect.TypeOf((*error)(nil)).Elem() mean in this code? I know if mType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() is trying to determine if the method's return type is error not not. But for me, reflect.TypeOf((error)(nil)) will intuitively will do the same, but unfortunately not. When I try to compile this code, it says type error is not an expression, what does it mean in this context? Does not reflect.Typeof() accepts a argument of certain type? I found that (*error)(nil) is equivalent to *error = nil. I am confused with this expression in the context above.
TL;DR; reflect.TypeOf((*error)(nil)).Elem() is an expression used to obtain the reflect.Type type descriptor of the interface type error. Using reflect.TypeOf(error(nil)) cannot be used for the same purpose (read the why below).
reflect.TypeOf((*error)(nil)).Elem() achieves its goal by using a typed nil pointer value of type *error, passing it to reflect.TypeOf() to get the reflect.Type descriptor of the type *error, and uses Type.Elem() to get the type descriptor of the element (base) type of *error, which is error.
reflect.TypeOf() expects an interface{} value:
func TypeOf(i interface{}) Type
Basically whatever value you pass to reflect.TypeOf(), if it's not already an interface value, it will be wrapped in an interface{} implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed as interface{}.
So if you try to pass an error value to it, since error is an interface type, the concrete value stored in it will be "repacked" into an interface{} value. The interface type error will not be retained / transferred!
If you pass a nil value of type error, e.g. error(nil), since the interface value itself is nil, it contains no concrete value and type, a nil interface{} value will be passed, that will result in nil reflect.Type returned. Quoting from reflect.TypeOf():
TypeOf returns the reflection Type that represents the dynamic type of i. If i is a nil interface value, TypeOf returns nil.
If you pass a value of type *error (which may be a nil pointer), it's not an interface value, it's a pointer value (a pointer to interface). So it will be wrapped in an interface{} value, and the concrete value stored in it will be of type *error. Using Type.Elem() you can access the pointed type, that is error.
This is one of the rare cases when using a pointer to interface makes sense, and in fact inevitable.
See related questions:
Get the reflect.Kind of a type which is based on a primitive type
What is the difference between reflect.ValueOf() and Value.Elem() in go?
Hiding nil values, understanding why golang fails here

Is it possible to have interface composite literals in Go?

I just want to confirm if my understanding is correct about interface{}{}
Does interface{}{} mean a composite literal of interface type?
So, if I wanted to pass a composite type, lets say []byte as a interface{}, I should assign it to a variable of type interface{}{} and pass in that variable, whereas if I wanted to pass a non composite type, such as a int as a interface{}, I should assign it to a variable of type interface{} and pass in that variable.
Is my understanding correct on this?
interface{}{} is invalid syntax.
It is not an empty interface composite literal — there's no such thing. The following don't compile:
var a interface{}{} = "foo" // not a type
b := interface{}{} // not a value
From the specs Composite Literals:
Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated.
The valid syntax is interface{}, which is the empty interface, i.e. an interface with no name and empty method set.
If you compare it to a named interface, you will see that the extra set of curly braces at the end makes no sense:
type Fooer interface {
Foo() error
}{} // ???
You can instantiate an empty interface{} by converting nil:
a := (interface{})(nil)
Or you can declare a var of unnamed interface type:
type A struct {}
func (a A) Foo() string {
return "foo"
}
var a interface{ Foo() string } = A{}
To answer your question:
So, if I wanted to pass a composite type [...]
you can assign any value to a variable of type interface{}, that's about it. Whether the value is composite or not is irrelevant because all types satisfy the empty interface:
var a interface{} = []byte{0x01, 0x02}
var b interface{} = "string_literal"
Playground: https://play.golang.org/p/w-l1dU-6Hb5
The empty interface interface{} essentially says "I don't care". Anything can be passed as an empty interface. So for your examples they all could be stored as the empty interface.
Possibly a more interesting question is why you want to avoid types in the first place, and what you're trying to achieve. But for the purposes of using interface{} you can pass anything to it, even a "nil".
interface{} type of empty interface.
you assign []byte or int to any empty variable of empty interface (interface{} type) or you can pass it directly to function that exepts interface values.

How can I return a subtype of the specified return value (in this case interface{})?

I have an interface that defines one parameter to have type func(interface{}, proto.Message) interface{} and I'm trying to pass something of type func reduceMsg(a interface{}, b proto.Message) []*PersistentData to it. This results in the following compiler error:
Cannot use reduceMsg (type func(a interface{}, b proto.Message) []*PersistentData as type func(interface{}, proto.Message) interface{}
What is the reason for this error, and how can I work around it? It seems like returning a more specific type than interface{} should be legal. Here's a simple complete example that illustrates the issue:
package main
import "fmt"
func main() {
var t func() interface{} = func() []string { return []string{} }
fmt.Println(t)
}
The type of the object is the whole function signature. If the signature don't match, then it's not the same type and can't be assigned that way.
Anything can be assigned to the empty interface, because all types satisfy the interface, but in your problem neither type is the empty interface, you just have a function that returns an empty interface.
Not because a part of the function can be assigned to another it makes it the same. The type is the whole function signature. I think it's the same logic behind not being able to assign an int to an int8. You can cast them if you want, but for go, they are separate types and you need to deal with making the necessary conversions to be able to assign them.
What you can do is change your second function signature to return an empty interface like this:
func(interface{}, proto.Message) interface{}
func reduceMsg(a interface{}, b proto.Message) interface{} {
var a []*PersistentData
// do something here
return a
}
This way the function signature is the same, so it's consider the same type and you are returning an []*PersistentData. Of course you will need to do a type assertion before using it as such because the program will treat it as an {}interface because that is the type that the function returned.
Referencing the spec,
In assignments, each value must be assignable to the type of the operand to which it is assigned, with the following special cases:
Any typed value may be assigned to the blank identifier.
If an untyped constant is assigned to a variable of interface type or the blank identifier, the constant is first converted to its default type.
If an untyped boolean value is assigned to a variable of interface type or the blank identifier, it is first converted to type bool.
Assignability
A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:
x's type is identical to T.
x's type V and T have identical underlying types and at least one of V or T is not a named type.
T is an interface type and x implements T.
x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type.
x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
x is an untyped constant representable by a value of type T.
In general, Go doesn't allow you to implicitly convert values from one type to another, with the exception of being able to use concrete-typed objects as though they were interfaces (that they implement).
In this particular case, since your function doesn't actually return an interface{}, the compiler would have to do some extra work to wrap up the return value as an interface{} and return it; if you really want to accomplish what you're trying you can do this explicitly yourself:
type Foo struct {
X int
}
func create(x int) Foo {
return Foo{X: x}
}
func main() {
var f func(int) interface{} = func(x int) interface{} {
return create(x)
}
}
which is basically doing (explicitly) the wrapping operation that you want the runtime to do implicitly.

Resources