Reflect
With reflect we get information about our variables at runtime.
It's highly recommended not to use reflection, because every wrong usage can panic.
Reflect should be the last possible way to do "meta-programming" in Go.
But let's check an example anyway:
output:
Reflection has three rules, that you should remember, when you work with reflect:
- Reflection goes from interface value to reflection object
- Reflection goes from reflection object to interface value
- To modify a reflection object, the value must be settable
Reflection goes from interface value to reflection object
If you use reflect.TypeOf you pass in any and get a Type back.
Type is an interface to get more information about the reflected type.
If we want to examine the Value of a specific variable we can do that by:
We can use the reflection to check, if a variable has a specific type:
output would be:
If you have a user-defined type, Type can give you the user-defined type, but Kind will always give you the built-in type.
Reflection goes from reflection object to interface value
If we have a reflected reflect.Value, we can derive back the inverse of it.
We call the Interface method on a Value to get it's interface again and then we can Type Assert it back to it's natural Go type.
Let's take an example:
output:
To modify a reflection object, the value must be settable
To set a value via reflection, the value must be settable.
output:
Go is call-by-value, therefore it's a copy of the variable x what reflect.ValueOf is using.
When we want to set the value of x, we have to pass a "Setable" type: a pointer.
If we now to set the value, the output would be:
Why? Because we just try to set 7.1 to the pointer itself and not to the actual value in RAM.
To get the actual Value of a pointer in the RAM we have to call [Elem].
Elem returns the value that the interface v contains or that the pointer v points to. It panics if v's Kind is not Interface or Pointer. It returns the zero Value if v is nil.
Example:
now the output is correct: