2

What is the equivalent of "id" function of Python in Golang?

id is what I normally use to compare if two objects are identical in Python (by crosschecking if their "id"s are the same. There are exceptions of course - like in PyTorch tensors sometimes, but mostly this works).

For the same in Golang I found that you can use the function mentioned in this answer which is DeepEqual. But was wondering if there's an equivalent of id in Python, which tbh is quite a convenient function to have.

Ambareesh
  • 324
  • 1
  • 4
  • 18
  • 2
    In Go, you don't need a function since if you have a pointer, you can compare it directly. And if you don't have a pointer, then two names always refer to two objects in different memory. – Charles Duffy Dec 18 '19 at 03:15
  • 1
    Which is to say, Python's `id` doesn't even make sense in Go. – Charles Duffy Dec 18 '19 at 03:16
  • 1
    (`id` can be used got identity comparison, but not equality comparison; cases where you'll get incorrect results misusing it for the latter are not rare in any respect whatsoever). – Charles Duffy Dec 18 '19 at 03:18
  • 3
    ... And actually, if you want to do identity comparison in Python, you don't need `id` for that either; you get more accurate results from the `is` operator. `id` will sometimes return the same result twice for things that aren't actually identical if an address is reused, making its use for identity comparison not just prone to false negatives, but false positives as well. – Charles Duffy Dec 18 '19 at 03:19
  • Python's id does not map neatly to all Go types, but there are some cases where it does. What types are you trying to compare? – Charlie Tumahai Dec 18 '19 at 05:02

3 Answers3

4

@satoru posted:

package main

import "fmt"

func main() {
    i := 32
    j := 32
    fmt.Printf("%p is %p\n", &i, &i)
    fmt.Printf("%p is not %p\n", &i, &j)
}

Output:

0xc000016100 is 0xc000016100
0xc000016100 is not 0xc000016108

Playground: https://play.golang.org/p/nXAEJeImeXa


However,

package main

import "fmt"

func main() {
    i := 32
    j := 32
    fmt.Printf("i %p is i %p; i == i %t\n", &i, &i, &i == &i)
    fmt.Printf("i %p is not j %p; i == j %t\n", &i, &j, &i == &j)

    fmt.Println()

    var v struct {
        i struct{}
        j struct{}
    }
    fmt.Printf("i %p is i %p; i == i %t\n", &v.i, &v.i, &v.i == &v.i)
    fmt.Printf("i %p is not j %p; i == j %t\n", &v.i, &v.j, &v.i == &v.j)
}

Output:

i 0x40e020 is i 0x40e020; i == i true
i 0x40e020 is not j 0x40e024; i == j false

i 0x1e52bc is i 0x1e52bc; i == i true
i 0x1e52bc is not j 0x1e52bc; i == j true

Playground: https://play.golang.org/p/Wv814ZgPCul


package cmp

import "github.com/google/go-cmp/cmp"

Package cmp determines equality of values.

This package is intended to be a more powerful and safer alternative to reflect.DeepEqual for comparing whether two values are semantically equal.

peterSO
  • 158,998
  • 31
  • 281
  • 276
1

With CPython, id returns the address of the object in memory. In Go, you get the pointer to objects with an ampersand:

package main

import "fmt"

func main() {
    i := 32
    j := 32
    fmt.Printf("%p is %p\n", &i, &i)
    fmt.Printf("%p is not %p\n", &i, &j)
}

The output of the example above looks like this on my machine:

0xc000016100 is 0xc000016100
0xc000016100 is not 0xc000016108
satoru
  • 31,822
  • 31
  • 91
  • 141
  • 2
    bad idea, really pointers are the domain of the runtime and it can do unexpected things. see peter's answer –  Dec 18 '19 at 10:32
0

You can use DeepEqual to compare the contents of two objects. However, I don't think that's what python id does. From the definition of id in python, it looks like pointer equivalence is what you're after, not DeepEqual. The function definition for id states

This is an integer which is guaranteed to be unique and constant for this object during its lifetime.

If you're comparing two pointer values, you can simply use ==: if two pointers point to the same thing, then they're equal. If two pointer values are not equal, they may still be pointing to objects with the same content though, so p1==p2 may be false, but DeepEqual(*p1,*p2) may be true.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59