How do I use reflect to check if the type of a struct field is interface{}? - go

I am using the reflect package to determine the type of a struct field is interface{}
I want to do the comparison like so (where t is a reflect.Type):
if t == reflect.TypeOf(interface{}) {
}
The problem is that the compiler complains: type interface {} is not an expression.
Is there anyway to check if the type of a struct field is an interface{}?

You can get the type of the interface Y by creating a nil instance and using reflection:
yType := reflect.TypeOf((*Y)(nil)).Elem()
and then use the expression
reflect.TypeOf(x).Implements(yType)
to check if the type implements the interface.
Interfaces themselves can not be instantiated. The interface{} interface which is the empty interface is implemented by all types so all fields implement that.
https://play.golang.org/p/gRfheIW_9Y
Actually it also works with the empty interface{} itself but this will always return true (if i'm not missing something):
https://play.golang.org/p/29rWP4LtIo

interface{} is a type, and reflect.TypeOf() expects a value. So you can't pass the literal interface{} to it. You can only pass a value.
Back to the original question. Let's see a struct example:
type My struct {
A int
B interface{}
C io.Reader
}
You want to tell if the type of a field is interface{}. Acquire the reflect.Type of the struct type, then you can access the fields using Type.Field() or Type.FieldByName().
This gives you a value of type reflect.StructField which stores the type of the field.
So far so good. But what should we compare it to? interface{} is an interface type with 0 methods. You can't have (instantiate) a value of that type. You can only have values of concrete types, but yes, they may be wrapped in an interface type.
You could use Type.Kind, and compare it to reflect.Interface, which tells you if it's an interface, but this is true for all interface types. You could also check if it has 0 methods with Type.NumMethod(), which must be 0 for interface{}, but other interfaces could also have 0 methods...
You may use Type.Name, but since interface{} is a unnamed type, its name is the empty string "" (and there are other unnamed types). You may use Type.String() which returns "interface {}" for the empty interface:
t := reflect.TypeOf(My{})
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
fmt.Printf("Field %q, type: %-12v, type name: %-8q, is interface{}: %v\n",
f.Name, f.Type,
f.Type.Name(),
f.Type.String() == "interface {}",
)
}
Output (try it on the Go Playground):
Field "A", type: int , type name: "int" , is interface{}: false
Field "B", type: interface {}, type name: "" , is interface{}: true
Field "C", type: io.Reader , type name: "Reader", is interface{}: false
You might find this related question interesting / useful: Identify non builtin-types using reflect

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 the reflect.Kind of a type which is based on a primitive type

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?

Set value of interface to struct field of type pointer to struc via reflection

I'm trying to set struct.field = &otherStruct. However, I have to use reflection, and otherStruct is of type interface{}.
The error I'm getting is:
reflect.Set: value of type main.StructB is not assignable to type *main.StructB
struct is known. The (real) type of otherStruct is not known, but it is guaranteed, that the assignment is safe (the struct type is identical).
Code:
type StrucA struct {
Field *StrucB
}
type StrucB struct {}
func main() {
a := StrucA{}
var b interface{} = StrucB{}
//above is set
// Target: Set a.Field = &b
reflect.ValueOf(&a).Elem().FieldByName("Field").Set(reflect.ValueOf(b)) // reflect.Set: value of type main.StrucB is not assignable to type *main.StrucB
}
Playground:
https://play.golang.org/p/LR_RgfBzsxa
I have tested a lot of different stuff, but I'm unable to solve it.
You first need to allocate a pointer to the type of b, in order to have somewhere to copy the value. Once you have a pointer value, you can set that to Field in a:
field := reflect.New(reflect.TypeOf(b))
field.Elem().Set(reflect.ValueOf(b))
reflect.ValueOf(&a).Elem().FieldByName("Field").Set(field)
https://play.golang.org/p/6-GNSEq0tw3

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.

Identify non builtin-types using reflect

I need to differentiate such types as
type A []byte
from a []byte. Using reflect, reflect.TypeOf(A{}).Kind tells me that it is a Slice of byte. How can I differentiate []byte{} from A{}, without having a bounded list of types to check for?
Are there new ways to do it in newer versions of Go?
Some background
First let's clear some things related to types. Quoting from Spec: Types:
A type determines the set of values and operations specific to values of that type. Types may be named or unnamed. Named types are specified by a (possibly qualified) type name; unnamed types are specified using a type literal, which composes a new type from existing types.
So there are (predeclared) named types such as string, int etc, and you may also create new named types using type declarations (which involves the type keyword) such as type MyInt int. And there are unnamed types which are the result of a type literal (applied to / including named or unnamed types) such as []int, struct{i int}, *int etc.
You can get the name of a named type using the Type.Name() method, which "returns an empty string for unnamed types":
var i int = 2
fmt.Printf("%q\n", reflect.TypeOf("abc").Name()) // Named: "string"
fmt.Printf("%q\n", reflect.TypeOf(int(2)).Name()) // Named: "int"
fmt.Printf("%q\n", reflect.TypeOf([]int{}).Name()) // Unnamed: ""
fmt.Printf("%q\n", reflect.TypeOf(struct{ i int }{}).Name()) // Unnamed: ""
fmt.Printf("%q\n", reflect.TypeOf(&struct{ i int }{}).Name()) // Unnamed: ""
fmt.Printf("%q\n", reflect.TypeOf(&i).Name()) // Unnamed: ""
There are types which are predeclared and are ready for you to use them (either as-is, or in type literals):
Named instances of the boolean, numeric, and string types are predeclared. Composite types—array, struct, pointer, function, interface, slice, map, and channel types—may be constructed using type literals.
Predeclared types are:
bool byte complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
You may use Type.PkgPath() to get a named type's package path, which "if the type was predeclared (string, error) or unnamed (*T, struct{}, []int), the package path will be the empty string":
fmt.Printf("%q\n", reflect.TypeOf("abc").PkgPath()) // Predeclared: ""
fmt.Printf("%q\n", reflect.TypeOf(A{}).PkgPath()) // Named: "main"
fmt.Printf("%q\n", reflect.TypeOf([]byte{}).PkgPath()) // Unnamed: ""
So you have 2 tools available to you: Type.Name() to tell if the type is a named type, and Type.PkgPath() to tell if the type is not predeclared and is a named type.
But care must be taken. If you use your own, named type in a type literal to construct a new type (e.g. []A), that will be an unnamed type (if you don't use the type keyword to construct a new, named type):
type ASlice []A
fmt.Printf("%q\n", reflect.TypeOf([]A{}).PkgPath()) // Also unnamed: ""
fmt.Printf("%q\n", reflect.TypeOf(ASlice{}).PkgPath()) // Named: "main"
What can you do in such cases? You may use Type.Elem() to get the type's element type, if type's Kind is Array, Chan, Map, Ptr, or Slice (else Type.Elem() panics):
fmt.Printf("%q\n", reflect.TypeOf([]A{}).Elem().Name()) // Element type: "A"
fmt.Printf("%q\n", reflect.TypeOf([]A{}).Elem().PkgPath()) // Which is named, so: "main"
Summary
Type.PkgPath() can be used to "filter out" predeclared and unnamed types. If PkgPath() returns a non-empty string, you can be sure it's a "custom" type. If it returns an empty string, it still may be an unnamed type (in which case Type.Name() returns "") constructed from a "custom" type; for that you may use Type.Elem() to see if it is constructed from a "custom" type, which may have to be applied recursively:
// [][]A -> Elem() -> []A which is still unnamed: ""
fmt.Printf("%q\n", reflect.TypeOf([][]A{}).Elem().PkgPath())
// [][]A -> Elem() -> []A -> Elem() -> A which is named: "main"
fmt.Printf("%q\n", reflect.TypeOf([][]A{}).Elem().Elem().PkgPath())
Try all the examples on the Go Playground.
Special case #1: Anonymous struct types
There is also the case of an anonymous struct type which is unnamed, but it may have a field of a "custom" type. This case can be handled by iterating over the fields of the struct type and performing the same check on each field, and if any of them is found to be a "custom" type, we can claim the whole struct type to be "custom".
Special case #2: Map types
In case of maps we may consider an unnamed map type "custom" if any of its key or value type is "custom".
The value type of a map can be queried with the above mentioned Type.Elem() method, and the key type of a map can be queried with the Type.Key() method - we also have to check this in case of maps.
Example implementation
func isCustom(t reflect.Type) bool {
if t.PkgPath() != "" {
return true
}
if k := t.Kind(); k == reflect.Array || k == reflect.Chan || k == reflect.Map ||
k == reflect.Ptr || k == reflect.Slice {
return isCustom(t.Elem()) || k == reflect.Map && isCustom(t.Key())
} else if k == reflect.Struct {
for i := t.NumField() - 1; i >= 0; i-- {
if isCustom(t.Field(i).Type) {
return true
}
}
}
return false
}
Testing it (try it on the Go Playground):
type K int
var i int = 2
fmt.Println(isCustom(reflect.TypeOf(""))) // false
fmt.Println(isCustom(reflect.TypeOf(int(2)))) // false
fmt.Println(isCustom(reflect.TypeOf([]int{}))) // false
fmt.Println(isCustom(reflect.TypeOf(struct{ i int }{}))) // false
fmt.Println(isCustom(reflect.TypeOf(&i))) // false
fmt.Println(isCustom(reflect.TypeOf(map[string]int{}))) // false
fmt.Println(isCustom(reflect.TypeOf(A{}))) // true
fmt.Println(isCustom(reflect.TypeOf(&A{}))) // true
fmt.Println(isCustom(reflect.TypeOf([]A{}))) // true
fmt.Println(isCustom(reflect.TypeOf([][]A{}))) // true
fmt.Println(isCustom(reflect.TypeOf(struct{ a A }{}))) // true
fmt.Println(isCustom(reflect.TypeOf(map[K]int{}))) // true
fmt.Println(isCustom(reflect.TypeOf(map[string]K{}))) // true

Resources