Why does printing of a (nil) map in golang yield a non "<nil>" result? - dictionary

In golang, if you create a struct with a map in it, which is uninitialized, printing the map yields a non <nil> string.
Why does "print" of a nil map output "map[]" instead of <nil> ?
// Assume above there is a struct, a.AA, which is created but which otherwise
// has not created the map.
//output:
//map[]
//map[]
fmt.Println(a.AA)
fmt.Println(make(map[string]int64))

It's just for making things clear. If you run this code:
var m map[string]int64
log.Println(m == nil)
log.Printf("%T\n", m)
It will print:
$ true
$ map[string]int64
So m is actually nil at this point. A nil value (can) have a type too and the formater uses that to print out something meaningful when possible.
A map behaves like a reference type in other languages. And in Go you can call methods of a struct even if its value is nil.
So even for your own structs, you can implement fmt.Stringer interface by just defining the String() string method on your struct and whenever your struct's value is nil you can print out something more proper than <nil>. Having:
type someData struct {
someValue string
}
func (x *someData) String() string {
if x == nil {
return "NO PROPER DATA HERE!"
}
return x.someValue
}
Then if we run:
var data *someData
log.Println(data)
data = new(someData)
data.someValue = "Aloha! :)"
log.Println(data)
The output will be:
$ NO PROPER DATA HERE!
$ Aloha! :)
See at the first line we did not get <nil> as output, despite the fact that our struct pointer is nil at that point.

A nil pointer is not the same as an empty (or zero) map. See https://golang.org/ref/spec#The_zero_value for authoritative information concerning zero values.
If you want a nil, you need a pointer, such as in the following example:
package main
import (
"fmt"
)
func main() {
var myMap map[string]int64
fmt.Printf("myMap before assignment: %v\n", myMap)
myMap = make(map[string]int64)
fmt.Printf("myMap after assignment : %v\n", myMap)
var myMapPointer *map[string]int64
fmt.Printf("myMapPointer before assignment: %v\n", myMapPointer)
myMapPointer = new(map[string]int64)
fmt.Printf("myMapPointer after assignment : %v\n", myMapPointer)
}
This gives:
myMap before assignment: map[]
myMap after assignment : map[]
myMapPointer before assignment: <nil>
myMapPointer after assignment : &map[]

Related

How can I reverse map using reflection

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.

Nil pointer to struct not deep equal to nil?

If I have a struct containing a nil pointer of type A, using reflect.DeepEqual to check if that property is nil will result in false, which strikes me as odd behaviour.
type Container struct {
O *Obj
}
type Obj struct {
Message string
}
var c Container
eq := reflect.DeepEqual(c.O, nil)
fmt.Printf("O value: %v, is nil: %t", c.O, eq)
// Prints: "O value: <nil>, is nil: false"
Specifically, I am marshaling a JSON object into a struct, where I would like to test that a specific property is nil when the corresponding JSON structure does not contain it. If reflect.DeepEqual is not the way to go, how should I do this?
Everything you pass to reflect.DeepEqual() is wrapped in an interface{} value (if it's not already that):
func DeepEqual(x, y interface{}) bool
interface{} values will be compared, where the first parameter value is not nil, only the value wrapped in it.
An interface value is represented as a (type; value) pair. The first value you pass to reflect.DeepEqual() is a pair of (type; value) being (*Obj, nil), and the 2nd value is nil. They are not equal. The second value lacks type information.
If you compare it to a "typed" nil, it will be true:
reflect.DeepEqual(c.O, (*Obj)(nil)) // This is true
See this example:
fmt.Println("c.O:", c.O)
fmt.Println("c.O == nil:", c.O == nil)
fmt.Println("c.O deep equal to nil:", reflect.DeepEqual(c.O, nil))
fmt.Println("c.O deep equal to (*Obj)(nil):", reflect.DeepEqual(c.O, (*Obj)(nil)))
Output (try it on the Go Playground):
c.O: <nil>
c.O == nil: true
c.O deep equal to nil: false
c.O deep equal to (*Obj)(nil): true
See this question for a deeper insight:
Hiding nil values, understanding why golang fails here
If you want to check if the value wrapped inside a non-nil interface is nil, you can use reflection: reflect.Value.IsNil().
For more details see: Why interface type doesn't provide an "IsNil" method?

Null vs nil in golang?

I ran into a strange bug today. I had a function:
func Foo(s *someStruct) {
fmt.Printf("s is %v\n", s)
if s!=nil {
fmt.Printf("s is not nil")
...
}
}
I would call the function like:
var s *someStruct
Foo(s)
And then I decided to convert the structure into interface:
func Foo(s someStructInterface) {
fmt.Printf("s is %v\n", s)
if s!=nil {
fmt.Printf("s is not nil")
...
}
}
Which gave me a strange output:
s is null
s is not nil
While I expected to get s is nil, which is what I was getting usually. What is the difference between null and nil in this scenario in Go and how can I check if something is null or nil to execute the code properly?
An interface value contains a reference to a type and a value. In the following code:
var s *someStruct
Foo(s)
the interface value passed to Foo contains a reference to the type *someStruct and a nil.
The statement fmt.Printf("s is %v\n", s) outputs s is <nil> because of the following:
The %v format prints a value using the default format for the type. The value s contains a pointer type. The default format for a pointer type is %p. The %p format prints nil pointers as <nil>.
The expression s != nil evaluates to true because an interface value is equal to nil if and only if the type reference is nil. In this case, the interface value references the type *someStruct.

Set an interface to nil in Golang

I'm trying to set an internal value of an interface to nil something like the following :
typ := &TYP{InternalState: "filled"}
setNil(typ)
fmt.Printf("Expecting that %v to be nil", typ)
And I need to know how to implement the setNil(typ interface{}) method.
For more details see this code in play.golang.org.
The thing is you don't have an interface value. You have a pointer value, a pointer to a concrete type. That is not the same as an interface value.
If you want to change the value of a variable of any type, you have to pass a pointer to it. This also includes variables of interface type, and also variables of pointer type. This is one of those very rare cases when a pointer to interface{} makes sense (*interface{}), in fact it's inevitable.
But if your function expects an interface and you pass a non-interface value, an interface value will be created implicitly and you could only nil this implicitly created value.
So we have 2 different / distinct cases:
Function to nil an interface{}
func setNilIf(v *interface{}) {
*v = nil
}
Using it:
var i interface{} = "Bob"
fmt.Printf("Before: %v\n", i)
setNilIf(&i)
fmt.Printf("After: %v\n", i)
Output:
Before: Bob
After: <nil>
So it works.
Function to nil a pointer; using unsafe
Actually this is your case. We want to change the value of a variable of pointer type. To accept a pointer to any type, we can use unsafe.Pointer. unsafe.Pointer is a language support, it's a special pointer type which can be converted from and to any pointer type.
We want to accept the address (pointer) of the pointer variable, which is something like **SomeType. To actually be able to assign a new value (nil) to the pointer variable, we have to dereference it (* operator). But unsafe.Pointer cannot be dereferenced, so first we have to convert it to a pointer to pointer to "something", but since we only want to assign nil (which is the same to all pointer types regardless of the type of the pointed value), the "something" doesn't matter, I will just use int, and so I will convert the unsafe.Pointer pointer value to **int.
func setNilPtr(p unsafe.Pointer) {
*(**int)(p) = nil
}
Using it:
typ := &TYP{InternalState: "filled"}
fmt.Printf("Before: %v\n", typ)
setNilPtr(unsafe.Pointer(&typ))
fmt.Printf("After: %v\n", typ)
Output:
Before: &{filled}
After: <nil>
So this one also works. There is still another way using reflection:
Function to nil a pointer; using reflect
You can also nil a pointer using reflection only (reflect package). We still have to pass the address of the variable of pointer type. Note that in this case the type of the parameter will simply be interface{}. And it will contain a dynamic type like **SomeType. Since pointers have zero value nil, we can obtain such a value with reflect.Zero() which we will set using Value.Set():
func setNilPtr2(i interface{}) {
v := reflect.ValueOf(i)
v.Elem().Set(reflect.Zero(v.Elem().Type()))
}
Using it:
typ2 := &TYP{InternalState: "filled"}
fmt.Printf("Before: %v\n", typ2)
setNilPtr2(&typ2)
fmt.Printf("After: %v\n", typ2)
Output:
Before: &{filled}
After: <nil>
So this one also works. Try these on the Go Playground.
But seriously: if you want to nil something, assign nil to it. Do not complicate things unnecessarily.
i = nil
typ = nil

Reflect thinks struct Value is also a ptr?

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)

Resources