This question already has answers here:
golang type assertion using reflect.Typeof()
(6 answers)
Closed 7 years ago.
My Problem is as follows:
I have a slice of reflect.Value, that was returned from a MethodByName("foo").Call().
now i want to cast the contained values to their types, which i dont know statically, but in form of relflect.Type
Basically what i want to do is:
values[0].Interface().(mytype)
but with reflection
values[0].Interface().(reflect.TypeOf(responseObject))
This gives me the compilation error:
reflect.TypeOf(responseObject) is not a type
Is there a way to do this in go?
Thanks and regards
BillDoor
If you have code using the normal type assertion syntax like:
x := v.(mytype)
Then the compiler knows that the variable x is of type mytype, and generates code accordingly. If the language let you use an expression in place of the type, then the compiler would have no way of knowing what type x is, and consequently no way to generate code that uses that variable.
If you only know the type of value at runtime, then you will need to stick with the reflect.Value API. You can determine the value's type using its Type method, and there are methods that will let you access struct fields, indexes in slices or arrays, etc.
You will only be able to move back to regular syntax when you have a type you know about at compile time.
What is a cast (type assertion)? It has two effects:
At compile time, the compile-time of the whole type assertion expression is the type casted to.
At runtime, a check is made on the actual runtime type of the value, and if it is not the type casted to, it will generate a runtime error.
Obviously, #1 doesn't make sense for a type that is not known at compile-time, because how can the compile-time type of something depend on something not known at compile time?
You can still do manually do #2 for a type that is not known at compile time. Just get the runtime type of the value using reflect.TypeOf() and compare it against the runtime.Type you have.
Related
This question already has an answer here:
Is this casting in golang?
(1 answer)
Closed 7 months ago.
After having issues understanding and being unable to access the ClusterComputeResourceSummary.UsageSummary field while working with govmomi, I was able to find a link that helped solve my problem, however, I am curious to understand how Golang is doing this behind the scenes, how after a chaining dot you provide the type you must obviously know before hand to extract the object and its properties?
usage := resource.Summary.(*types.ClusterComputeResourceSummary).UsageSummary
How can I go about reading this syntax, especially the part after .(*types.ClusterComputeResourceSummary) ?
P.S. Forgive me for the question title, honestly I don't know the right term or lingo for this use case, like is this reflection or something similar?
This is a "type assertion". The resource.Summary is an interface value that contains a pointer to an object, and its type. The type assertion checks if the type you gave *types.ClusterComputeResourcesSummary can be assigned to the type of data stored in the interface, and if so, returns the value stored in the interface as an instance of that type. Then you can access the members/methods of that variable.
This question already has answers here:
Explain Type Assertions in Go
(3 answers)
Closed 8 months ago.
I was going through this tour of go.
Initially i is declared an interface with type string.
var i interface{} = "hello"
But when we do
f = i.(float64) // panic
My question is, why isn't this caught during compile time in golang.
C++ generics catch this during compile time, unlike go which decides to do it at runtime.
The "type" information for i exists during compilation.
This kind of issue would be something that would make it easier (from a golang programmer's perspective) to catch during compilation than runtime.
edit: Eduardo Thales suggested that generics were included later in golang. I was under the assumption that the underlying mechanism of interfaces is generics. apparently not. Thanks Eduardo
The language specification explicitly says that false type assertions cause a run-time panic. See:
If the type assertion is false, a run-time panic occurs.
Also, there's nothing in the language that says that you can't make a program that will unambiguously panic. For example, this is a valid program that will compile without error:
package main
import "fmt"
func main() {
fmt.Println("Don't panic!")
panic(1)
}
You're mixing up generics and variable types.
Take this as an example:
items := []string{"item1", "item2"}
fmt.Println(slices.Contains(items, "item1"))
The variable type is slice. The generic part is string, which is regarded in slices.Contains.
So, fmt.Println(slices.Contains(items, 1)) would cause a compile time error because the generic type string doesn't match the generic type int.
(NB: slice is not the best representative of a typical generic in Go because usually they look different, but it's the easiest one to grasp the concept.)
#mkopriva has already answered why your code doesn't cause a compile error: float64 is a valid subtype of interface{}.
If it wasn't, you'ld get a compile time error here as well, e.g. as in
var i string = "hello"
f := i.(float64) // compile time error
Generics don't even exist here, though, and neither they did in your example.
This question already has answers here:
What are the benefits of replacing an interface argument with a type parameter?
(2 answers)
Closed 8 months ago.
In the new Type Parameters Design Draft, you can now apply an interface constraint to a generic function:
func prettyPrint[T Stringer](s T) string {
...
}
But, this was already possible by using an interface parameter without generics:
func prettyPrint(s Stringer) string {
...
}
What's the difference between using the first and using the second?
I assume the question refers to the latest draft of the Type Parameters proposal, which may end up in Go in 1.18.
The first is parametric polymorphism. The compiler verifies that the constraint is satisfied, and then generates code that takes a statically-known type. Importantly, it's not boxed.
The second is runtime polymorphism. It takes a type that's unknown at compile time (the only thing known is that it implements the interface) and works on a boxed interface pointer.
Performance considerations aside, in this simple case you can use either approach. Generics really help with the more complicated cases where the current tools don't work well.
For example, in the following example from IOKit documentation, each entry for this device has different types, such as Data, Number, etc
How can I use IOKit to read the type of it? I know that we can use IORegistryEntryCreateCFProperties to create a dictionary for an entry and read the property as void pointer and cast it to the type we know it is, but how can I know its type without taking a look using IORegistry Explorer?
Note that you can use a similar function, IORegistryEntryCreateCFProperty to query only one property, which is usually more useful unless you're actually trying to build something similar to IORegistryExplorer itself and don't yet know the names of the properties you want to inspect.
In both cases, this really boils down to a Core Foundation question. You'll notice that rather than a truly opaque void*, IORegistryEntryCreateCFProperty() actually returns a CFTypeRef, and likewise, IORegistryEntryCreateCFProperties() promises to only return CoreFoundation-type objects in its dictionary. This means you can query the object's type using CFGetTypeID(). The exact value of this is meaningless, but it can be compared to the type IDs for the expected set of types, e.g. CFStringGetTypeID() for CFString, CFDataGetTypeID() for CFData and so on.
If you're using Objective-C, you can also perform a bridging cast and treat the property values as NSObject - and then find out the specific type using e.g. [object isKindOfClass:[NSString class]].
If I have a name of a type (i.e "container/vector"), is there a way to lookup the reflect.Type that has the given name? I'm trying to write a simple database-backed workqueue system and this it would be very difficult without this feature.
I can't see how this would be possible in any trivial way (or at all), since name resolution is part of the compiler/linker, not the runtime.
However, http://github.com/nsf/gocode might offer up some ideas. Though I'm pretty sure that works by processing the .a files in $GOROOT, so I still don't see how you'd get the reflect.Type. Maybe if the exp/eval package was more mature?
Of course if you know all the possible types you'll encounter, you could always make a map of the reflect.Type. But I'm assuming you're working with unpredictable input, or you would've thought of that.
Only way to create a reflect.Type is by having a concrete value of the intended type first. You can't even create composite-types, such as a slice ([]T), from a base type (T).
The only way to go from a string to a reflect.Type is by entering the mapping yourself.
mapping := map[string]reflect.Type {
"string": reflect.Typeof(""),
"container/vector": reflect.Typeof(new(vector.Vector)),
/* ... */
}