2

Go maps are references to internal data. Meaning that when a map is "copied", they end up sharing the same reference and thus editing the same data. This is something highly different than having another map with the same items. However, I cannot find any way to tell the difference between both cases.

import "fmt"
import "reflect"

func main() {
    a := map[string]string{"a": "a", "b": "b"}
    // b references the same data as a
    b := a
    // thus editing b also edits a
    b["c"] = "c"
    // c is a different map, but with same items
    c := map[string]string{"a": "a", "b": "b", "c": "c"}

    reflect.DeepEqual(a, b) // true
    reflect.DeepEqual(a, c) // true too
    a == b // illegal
    a == c // illegal too
    &a == &b // false
    &a == &c // false too
    *a == *b // illegal
    *a == *c // illegal too
}

Any solution for that ?

Aurélien Lambert
  • 712
  • 1
  • 8
  • 12
  • All 3 maps in your code contain the same data, hence they are equal. – zerkms Oct 31 '19 at 04:02
  • 4
    Come on, there is a huge difference between "we contain the same elements right now" and "we will have the same elements whatever modification you do". – Aurélien Lambert Oct 31 '19 at 04:15
  • 1
    According to https://golang.org/ref/spec#Type_identity: "Two map types are identical if they have identical key and element types." Hence `reflect.DeepEqual()` return `true`. And https://golang.org/ref/spec#Comparison_operators state that: "Slice, map, and function values are not comparable." So I am not sure if there is a way to show `b` and `c` are different. Also, Dave Cheney shows that [map is not reference variable](https://dave.cheney.net/2017/04/30/if-a-map-isnt-a-reference-variable-what-is-it). – FuXiang Shu Oct 31 '19 at 04:22
  • 2
    There is no difference. I have no idea what you are trying to do. Say your maps are of type `map[string]**int`. Even if you populate the maps with distinct `**int` their values still might point to the same `int` and modifying through one "modifies" the other. There is a _reason_ why equality on map values is undefined. Is this some kind of XY problem? – Volker Oct 31 '19 at 04:27

1 Answers1

7

Use the reflect package to compare the maps as pointers:

func same(x, y interface{}) bool {
    return reflect.ValueOf(x).Pointer() == reflect.ValueOf(y).Pointer()
}

Use it like this on the maps in the question:

fmt.Println(same(a, b)) // prints true
fmt.Println(same(a, c)) // prints false
Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242