I am curious about IsValid function, because during my use of this function, it never returned false. So when does it return a negative result?
As the doc reflect.IsValid() says:
It returns false if v is the zero Value. [...]
Most functions and methods never return an invalid value. If one does, its documentation states the conditions explicitly.
Value.IsValid() is supposed to report whether the reflect.Value itself is valid, not the value it wraps (if any).
All the examples below print false. You can try them on the Go Playground.
The simplest example is calling IsValid() on the zero value of reflect.Value (which is a struct):
fmt.Println(reflect.Value{}.IsValid())
The 2nd simplest example is when passing nil to reflect.ValueOf():
fmt.Println(reflect.ValueOf(nil).IsValid())
Another example: start with a pointer being nil, in this case there is no "pointed" value, a nil pointer points to nowhere. Attempting to get the reflect.Value of the pointed value using Value.Elem() results in a zero reflect.Value whose IsValid() method will return false:
var i *int
v := reflect.ValueOf(i)
v2 := v.Elem()
fmt.Println(v2.IsValid())
Or in one line:
fmt.Println(reflect.ValueOf((*int)(nil)).Elem().IsValid())
Same thing if you call Value.Indirect() on the above reflect.Value():
fmt.Println(reflect.Indirect(v).IsValid())
Or attempting to get a non-existing struct field by name using Value.FieldByName():
s := struct{}{}
fmt.Println(reflect.ValueOf(s).FieldByName("").IsValid())
Or attempting to get a non-existing method by name using Value.MethodByName():
fmt.Println(reflect.ValueOf(s).MethodByName("").IsValid())
Or attempting to get a value from a map by a non-existing key using Value.MapIndex():
m := map[int]int{}
fmt.Println(reflect.ValueOf(m).MapIndex(reflect.ValueOf(3)).IsValid())
The list goes on...
Related
I'm struggling trying to figure out how to "extract" an integer value from a interface that holds a value whose dynamic type is pointer to integer.
You may follow this ready-to-run example in order to fully get the picture of what is problem and my intention.
TD;DR:
For some reason the reflection on a first call to reflect.ValueOf(value) over an interface whose dynamic type is pointer to integer, it returns a value whose Kind() results in reflect.Ptr, when i extract again the "inner" value using reflect.ValueOf(value).Elem() i get another value whose Kind() results in reflect.Struct. I don't even code any struct, but they appears by their own "magically". So golang may not panic but i don't understand what is happening, probably i lack of some information. I would be very thankful with anyone that explaint me what is going on.
This may work for this case, but it doesn't enlight me. I would expect to have an integer value "behind" the pointer. I don't need to access for modification, i only need to get it.
It's struct because when you call ToCompliantValue inside the function, you're not passing it the value itself, you're passing a reflect.Value value, and reflect.Value is a struct. You have to handle it directly instead of trying to use recursion:
v := reflect.ValueOf(value)
fmt.Printf("Value is %+v\n", v)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
// ...
Working example: https://play.golang.org/p/ndRjXJfj5xV
I started learning golang a couple of days ago and found reflect.Valueof() and Value.Elem() quite confusing. What is the difference between this two function/methods and how to use them correctly?
Both function/methods return a Value, and according to the go doc
ValueOf returns a new Value initialized to the concrete value stored in the interface i. ValueOf(nil) returns the zero Value.
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 Ptr. It returns the zero Value if v is nil.
I found this code from a post on stackoverflow but still don't understand when to use .Elem()
func SetField(obj interface{}, name string, value interface{}) error {
// won't work if I remove .Elem()
structValue := reflect.ValueOf(obj).Elem()
structFieldValue := structValue.FieldByName(name)
if !structFieldValue.IsValid() {
return fmt.Errorf("No such field: %s in obj", name)
}
if !structFieldValue.CanSet() {
return fmt.Errorf("Cannot set %s field value", name)
}
structFieldType := structFieldValue.Type()
// won't work either if I add .Elem() to the end
val := reflect.ValueOf(value)
if structFieldType != val.Type() {
return fmt.Errorf("Provided value %v type %v didn't match obj field type %v",val,val.Type(),structFieldType)
}
structFieldValue.Set(val)
return nil
}
reflect.ValueOf() is a function, think of it as the entry point to reflection. When you have a "non-reflection" value, such as a string or int, you can use reflect.ValueOf() to get a reflect.Value descriptor of it.
Value.Elem() is a method of reflect.Value. So you can only use this if you already have a reflect.Value. You may use Value.Elem() to get the value (reflect.Value) pointed by the value wrapped by the original reflect.Value. Note that you may also use reflect.Indirect() for this. There's another "use case" for Value.Elem(), but it's more "advanced", we return to it at the end of the answer.
To "leave" reflection, you may use the general Value.Interface() method, which returns you the wrapped value as an interface{}.
For example:
var i int = 3
var p *int = &i
fmt.Println(p, i)
v := reflect.ValueOf(p)
fmt.Println(v.Interface()) // This is the p pointer
v2 := v.Elem()
fmt.Println(v2.Interface()) // This is i's value: 3
This will output (try it on the Go Playground):
0x414020 3
0x414020
3
For a great introduction to Go's reflection, read The Go Blog: The Laws of Reflection. Although if you're just starting with Go, I'd focus on other things and leave reflection for a later adventure.
Another use case for Value.Elem()
This is kind of an advanced topic, so don't freak out if you don't understand it. You don't need to.
We saw how Value.Elem() can be used to "navigate" when a pointer is wrapped in the reflect.Value. Doc of Value.Elem() says:
Elem returns the value that the interface v contains or that the pointer v points to.
So if reflect.Value wraps an interface value, Value.Elem() may also be used to get the concrete value wrapped in that interface value.
Interfaces in Go is its own topic, for the internals, you may read Go Data Structures: Interfaces by Russ Cox. Again, not necessarily a topic for Go starters.
Basically whatever value you pass to reflect.ValueOf(), 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{}. This second "use case" surfaces if you pass a pointer to interface (which is otherwise very rare in Go!).
So if you pass a pointer to interface, this pointer will be wrapped in an interface{} value. You may use Value.Elem() to get the pointed value, which will be an interface value (not a concrete value), and using Value.Elem() again on this will give you the concrete value.
This example illustrates it:
var r io.Reader = os.Stdin // os.Stdin is of type *os.File which implements io.Reader
v := reflect.ValueOf(r) // r is interface wrapping *os.File value
fmt.Println(v.Type()) // *os.File
v2 := reflect.ValueOf(&r) // pointer passed, will be wrapped in interface{}
fmt.Println(v2.Type()) // *io.Reader
fmt.Println(v2.Elem().Type()) // navigate to pointed: io.Reader (interface type)
fmt.Println(v2.Elem().Elem().Type()) // 2nd Elem(): get concrete value in interface: *os.File
Try it on the Go Playground.
In golang reflect package, reflect.value.IsValid has those comments:
IsValid reports whether v represents a value. It returns false if v is the zero Value. If IsValid returns false, all other methods except String panic. Most functions and methods never return an invalid value. If one does, its documentation states the conditions explicitly.
Read above, i am very confused. i don't know what is zero value of reflect.Value and use it call isValid get false.
I write some code to test:
var haha *int
fmt.Println(reflect.ValueOf(haha).IsValid()) //true
var hehe interface{}
fmt.Println(reflect.ValueOf(hehe).IsValid() //false
A zero value is the default initialization value that is written to the memory address when no explicit initialization is provided. Tesing if v is a zero value is, in fact, testing if you have initialized v.
var haha *int returns true because haha is a pointer and cannot be created with an rational "default zero value", otherwise it would point to a random address in your memory and could have dangerous side effects. Pointers are nil when they are created, when other data types will have an actual value.
On the other hand, the zero value of var hehe interface{} is a nil *int, which is an actual entity.
I have read some text regarding nil slice vs empty slice. I believe I have some basic understanding of the differences between them.
Summary of my understanding: var instance []Type is nil slice and instance == nil returns true; while instance:=[]Type{} is empty slice and instance != nil
However this particular instance still puzzles me.
Please look at the link below for code. My question is the last 2 cases.
https://play.golang.org/p/udyHoOlSeP
Suppose I want to compare two slices, renamed type and interface matching and all. The instance where a receiver can be nil, even though it's not defined as copy by value; while the argument is copied by value, seems to
be non-nil as long as the argument is not untyped.
In the last 2 cases, receiver has been identified as nil while argument is being processed by := so it becomes an empty slice. (But the other == nil also reports false...) How can I fix this to satisfy the following requirement?
nilslice.Equals(nilslice) // -> true
Further, I tried to define another interface comparing to pointers of interface but failed. Compiler complains that
cannot use p (type *AnotherNullable) as type *PointerComparable in argument to AnotherNullable(nil).Equals:
*PointerComparable is pointer to interface, not interface
https://play.golang.org/p/wYO1GKcBds
How can I fix that?
EDIT: Thanks to #zippoxer for all the insights. I learned a lot. I hope new readers too, please don't forget to check out #zippoxer's comment in the answer too!
First, you don't need a pointer to an interface. An interface is already a pointer.
See Go: What's the meaning of interface{}?
Just change the Equals method to accept a PointerComparable instead of a *PointerComparable. Equals will accept an interface instead of a pointer to an interface, but you can still pass a pointer to a slice/whatever to it.
See https://play.golang.org/p/e_Gtq2oAFA
Second, the receiver Nullable isn't an interface, while the argument you pass to Equals is an interface. That would explain why the Nullable receiver stays nil and the Comparable argument isn't nil although it's underlying slice is. The thing is, the Comparable argument is an interface that points to something, so whatever it points to, it won't be nil.
This code explains the problem:
var a interface{}
fmt.Println(a == nil) // true, the interface doesn't point to anything
var someNilSlice []int
fmt.Println(someNilSlice == nil) // true, just some nil slice
a = someNilSlice
fmt.Println(a == nil) // false, now the interface does point to something
From the docs
func (v Value) Elem() Value
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 Ptr. It returns the zero Value if v is nil.
func Indirect(v Value) Value
Indirect returns the value that v points to. If v is a nil pointer, Indirect returns a zero Value. If v is not a pointer, Indirect returns v.
So can I safely assume the following?
reflect.Indirect(reflect.ValueOf(someX)) === reflect.ValueOf(someX).Elem().
Is Indirect method just a convenience method for the right hand side of the above?
If a reflect.Value is a pointer, then v.Elem() is equivalent to reflect.Indirect(v). If it is not a pointer, then they are not equivalent:
If the value is an interface then reflect.Indirect(v) will return the same value, while v.Elem() will return the contained dynamic value.
If the value is something else, then v.Elem() will panic.
The reflect.Indirect helper is intended for cases where you want to accept either a particular type, or a pointer to that type. One example is the database/sql conversion routines: by using reflect.Indirect, it can use the same code paths to handle the various types and pointers to those types.