Under what circumstances could this code:
v, ok := value.(int64)
if !ok {
panic("NOPE "+reflect.TypeOf(value).Kind().String())
} else {
fmt.Printf("VAL: %d\n",v)
}
produce the panic with message panic: NOPE int64?
Is this a bug or is there something basic about the numeric types that I'm missing?
This can happen if you're using type declaration on numeric types. If you do something like this:
type T int64
...
var value interface{} = T(1)
and put it into your code, you'll get the exact same error. But if you don't check the kind, but the type, you'll see what's happening here:
v, ok := value.(int64)
if !ok {
panic("NOPE " + reflect.TypeOf(value).String())
} else {
fmt.Printf("VAL: %d\n", v)
}
produces the message:
panic: NOPE main.T
The kind of T is int64, but value is not int64.
Related
I am studying reflect in Go and trying to implement function which get map and return another map, where keys will be values and values will be keys.
Example:
m := map[string]int{"one": 1, "two": 2}
fmt.Println(ReverseMap(m)) // {1: "one", 2: "two"}
Here is my code:
func ReverseMap(in interface{}) interface{} {
var out reflect.Value
v := reflect.ValueOf(in)
if v.Kind() == reflect.Map {
for idx, key := range v.MapKeys() {
value := v.MapIndex(key)
if idx == 0 {
mapType := reflect.MapOf(reflect.TypeOf(value), reflect.TypeOf(key))
out = reflect.MakeMap(mapType)
}
out.SetMapIndex(value, key)
}
}
return out
}
This code panic with error:
panic: reflect.Value.SetMapIndex: value of type int is not assignable to type reflect.Value
I think the reason of this error is the declaration of out variable, but I don't know how to declare it correctly, if I don't know the type of this variable.
How can I fix this error?
The key and value are of type reflect.Value, so passing them to reflect.TypeOf() will not return the type descriptors of the key and value types of the map (string and int), but instead the type descriptor of the reflect.Value type itself.
Instead simply call their Value.Type() method:
mapType := reflect.MapOf(value.Type(), key.Type())
With this it'll (almost) work and print (try it on the Go Playground):
map[1:one 2:two]
I wrote "almost" because you're returning a reflect.Value, not a map. But if a reflect.Value is passed to the fmt package, it prints the value wrapped inside it:
If the operand is a reflect.Value, the operand is replaced by the concrete value that it holds, and printing continues with the next rule.
So you should call Value.Interface() on out before returning it.
It's easier to return early if the kind is not map, so you can create the map right after that:
func ReverseMap(in interface{}) interface{} {
v := reflect.ValueOf(in)
if v.Kind() != reflect.Map {
return nil
}
mapType := reflect.MapOf(v.Type().Elem(), v.Type().Key())
out := reflect.MakeMap(mapType)
for _, key := range v.MapKeys() {
out.SetMapIndex(v.MapIndex(key), key)
}
return out.Interface()
}
Try this variant on the Go Playground.
Another approach may be using Value.MapRange():
for iter := v.MapRange(); iter.Next(); {
out.SetMapIndex(iter.Value(), iter.Key())
}
Try this variant on the Go Playground.
Say I have two structs that define a linked list:
....
....
type node struct {
item interface{}
next *node
}
type LinkedList struct {
first *node
N int
}
...
...
and I want to compare the value of the type of the underlying node, say, in a find function where we check if k == node.item such that:
func (l *LinkedList) find (key interface{}) bool {
result := false
if !l.isEmpty() {
for x:= l.first; x != nil; x = x.next {
if x.item == key {
result = true
break
}
}
return result
}
this will not work for the expected find function because the underlying types are different, hence the func will always return false. We can confirm this upon reflecting the type:
fmt.Println(reflect.TypeOf(key), reflect.TypeOf(x.item))
>>> string, *main.node
Tried workarounds?
I've tried asserting the type but alas this does not work and panics
tmp := x.item.(string)
>>>panic: interface conversion: interface {} is *main.node, not string
This case is the same for using fmt.Sprintf(x.item)
I'm a bit stumped as to where to go from here. Is there a way to do this?
Inserting item to linked list
The following snippet should clarify how insertion is handled
func (l *LinkedList) insertFirst(item interface{}) {
var first *node = new(node)
oldfirst := l.first
first.item = item
first.next = oldfirst
l.first = first
l.N++
}
.....
//which gets called somewhere like
var n *node = new(node)
n.item = item
l.insertFirst(n)
.....wait no theres the error!
----------
burak-serdar you are 100% correct that I am inserting the node in the node!
The interface comparison in find() is a valid comparison and it will work if the type of the key and the type of the value stored in the node are the same. However, evidence points to you adding a node in place of a value.
In below code, in order to show the expected type, I have to create a new object and call reflect.TypeOf on it.
package main
import (
"fmt"
"reflect"
)
type X struct {
name string
}
func check(something interface{}) {
if _, ok := something.(*X); !ok {
fmt.Printf("Expecting type %v, got %v\n",
reflect.TypeOf(X{}), reflect.TypeOf(something))
}
}
func main()
check(struct{}{})
}
Perhaps that object creation is not an overhead, but I still curious to know a better way. Are there something like X.getName() or X.getSimpleName() in java?
To obtain the reflect.Type descriptor of a type, you may use
reflect.TypeOf((*X)(nil)).Elem()
to avoid having to create a value of type X. See these questions for more details:
How to get the string representation of a type?
Golang TypeOf without an instance and passing result to a func
And to print the type of some value, you may use fmt.Printf("%T, something).
And actually for what you want to do, you may put reflection aside completely, simply do:
fmt.Printf("Expecting type %T, got %T\n", (*X)(nil), something)
Output will be (try it on the Go Playground):
Expecting type *main.X, got struct {}
Using reflects is almost always a bad choice. You can consider using one of the following ways
Use switch
If you want to control the flow depending on the type you can use the switch construction
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Twice %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
Use fmt package
If you want only to display its type you can always use the fmt package
i := 1000
fmt.Printf("The type is %T", i)
Say I have this struct:
type Foo struct {
Bar *string `json:"bar"`
Baz *int64 `json:"baz,omitempty"`
Qux *string `json:"qux"`
Quux string `json:"quux"`
}
After unmarshalling the json, I check for nil like so:
switch {
case f.Bar == nil:
return errors.New("Missing 'bar'")
case f.Baz == nil:
f.Baz = 42
case f.Qux == nil:
return errors.New("Missing 'qux'")
}
(or through a series of if statements, etc...)
I understand that I can put all the nil comparisons in one comma separated case, but each nil check will have differing returns.
My question: is there a less verbose way of doing the nil checks?
A question to you: how less verbose you want to get? Because you want to do different things on different conditions (different fields being nil). Your code contains these different things and the different conditions. Beyond that what's "redundant" in your code are just the switch and case keywords. You want to leave them out? Because the rest is not "redundant", they are required.
Also note that in Go cases do not fall through even without a break (unlike in other languages), so in your above example if f.Baz is nil, you will set it to 42 and f.Qux will not be checked (so no error will be returned), but if f.Baz is non-nil and f.Qux is nil, an error will be returned. I know it's just an example, but this is something to keep in mind. You should handle errors first if you use a switch! Or use if statements and then the error will be detected and returned regardless of the order of field checks.
Your code with switch is clean and efficient. If you want to make it less verbose, readability (and performance) will suffer.
You may use a helper function which checks if a pointer value is nil:
func n(i interface{}) bool {
v := reflect.ValueOf(i)
return v.Kind() == reflect.Ptr && v.IsNil()
}
And using it:
func check(f *Foo) error {
switch {
case n(f.Bar):
return errors.New("Missing 'bar'")
case n(f.Qux):
return errors.New("Missing 'qux'")
case n(f.Baz):
x := int64(42)
f.Baz = &x
}
return nil
}
Or using if statements:
func check2(f *Foo) error {
if n(f.Bar) {
return errors.New("Missing 'bar'")
}
if n(f.Qux) {
return errors.New("Missing 'qux'")
}
if n(f.Baz) {
x := int64(42)
f.Baz = &x
}
return nil
}
Try these on the Go Playground.
I have a data structure like this demo. As you can see, foo has an embedded pointer to bar:
type foo struct {
*bar
}
type bar struct {
S []byte
}
And I'm using the reflect package like this:
func test(x interface{}) {
var v = reflect.ValueOf(x)
if v.Kind() == reflect.Struct {
fmt.Println("was a struct")
// panic: reflect: call of reflect.Value.Elem on struct Value
// v = v.Elem()
// panic: reflect: call of reflect.Value.Field on ptr Value
v = v.FieldByName("S")
}
}
func main() {
var f foo
test(f)
fmt.Println(string(f.S))
}
So v.Kind() is recognized as a reflect.Struct, but if I try to treat it like a struct by using .FieldByName("S"), it panics because it thinks v is a ptr.
So then if I try to treat it like a ptr by calling .Elem(), it panics because it thinks v is a struct.
I've tried reflect.Indirect(), as well as a few other things, but I can't figure out how to get the field of an embedded pointer.
Is there a way to get the reflect.Value representation from an embedded pointer to a struct?
Demo: http://play.golang.org/p/n0eea6XW3I
EDIT: Also tried v = v.FieldByName("bar"), but got:
panic: runtime error: invalid memory address or nil pointer dereference
The first thing we need to realize is that the line var f foo is equivalent to f := foo{}. This initializes the internal field bar (of type *bar) to its zero value... nil. The behavior of embedded types and reflect seems to be that it treats the embedded type's fields as fields of the type itself. So when you request v.FieldByName("S") it's trying to find that field in f's member, bar, which is nil.
You're trying to do this (*f.bar).S. (In Go the explicit pointer dereference isn't needed, but it makes my point). Now the question is: if you change is to v.FieldByName("bar") why does it give an error? Same reason.
Look closely at the stack trace, the FieldByName line no longer crashes, the line that crashes is fmt.Println(string(f.S)). Again, semantically you're doing (*f.bar).S. But the member "bar" is nil, so you are, in fact, doing a nil pointer dereference.
You can fix both errors by changing var f foo to f := foo{&bar{}}.
i was getting this error " panic: reflect: call of reflect.Value.Elem on struct Value" bcz of this line "reflect.ValueOf(parameterName).Elem()"
1.When i am using Elem() in reflex ,it means parameterName inside valueOf() should be a pointer to structure
func Search(flight interface{}, key string) string {
val := reflect.ValueOf(flight).Elem()
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
if key == strings.ToLower(typeField.Name) {
return valueField.Interface().(string)
}
}
return ""
}
Now while calling search function my call should be like this!
result := Search(&flights, key)