Object equality

4,014 views
Skip to first unread message

Esko Luontola

unread,
Dec 2, 2009, 5:53:51 PM12/2/09
to golang-nuts
I'm writing a testing framework for Go (http://github.com/orfjackal/
gospec) and right now I'm faced with the issue that how object
equality in Go is defined (or actually, is not defined). Since the ==
operator is defined only for some of the built-in types, comparing two
objects for equality is troublesome - it will crash the program.

The current approach that I use is to have an interface:

type Equality interface {
Equals(other interface{}) bool;
}

Which is then implemented like this:

type DummyStruct struct {
value int;
ignoredValue int;
}

func (this DummyStruct) Equals(other interface{}) bool {
if that, ok := other.(DummyStruct); ok {
return this.equals(&that)
}
if that, ok := other.(*DummyStruct); ok {
return this.equals(that)
}
return false
}

func (this *DummyStruct) equals(that *DummyStruct) bool {
return this.value == that.value
}

And the testing framework then uses the following function for object
equality:

func areEqual(a interface{}, b interface{}) bool {
if a2, ok := a.(Equality); ok {
return a2.Equals(b)
}
return a == b
}

Would there be some better way for defining object equality? Using the
== operator with any objects which implement some standard interface
would be nice.

Some related discussion:

http://groups.google.com/group/golang-nuts/browse_thread/thread/1dda033987a5de53/f7f4fea4123c0afe
http://groups.google.com/group/golang-nuts/browse_thread/thread/3c7464fdaf00e3c9/68be6827d8d2438a
http://groups.google.com/group/golang-nuts/browse_thread/thread/b91933187bd51d22/9774cdb3cf33c28d

Dimiter "malkia" Stanev

unread,
Dec 2, 2009, 6:17:54 PM12/2/09
to golang-nuts
What if you print the objects to a string and compare the results? Yes
it's not check for equality - they might print the same, but to be
different - then again this might be what you want.

package main

import "fmt"

func main()
{
var m1 map[string]int;
var m2 map[string]int;
m1 = make(map[string]int);
m2 = make(map[string]int);
m1["test1"] = 10;
m1["test2"] = 20;
m2["test2"] = 20;
m2["test1"] = 10;
fmt.Printf( "%v\n", m1 );
fmt.Printf( "%v\n", m2 );
}

Prints out this:

map[test1:10 test2:20]
map[test1:10 test2:20]
> http://groups.google.com/group/golang-nuts/browse_thread/thread/1dda0...http://groups.google.com/group/golang-nuts/browse_thread/thread/3c746...http://groups.google.com/group/golang-nuts/browse_thread/thread/b9193...

Esko Luontola

unread,
Dec 2, 2009, 7:12:21 PM12/2/09
to golang-nuts
For the built-in collections I'll add some special handling for
equality (similar to JDave http://www.jdave.org/documentation.html).
The main problem is that how an application programmer can define an
equality contract for his own objects/structs.
Message has been deleted

Ian Lance Taylor

unread,
Dec 2, 2009, 7:40:23 PM12/2/09
to Esko Luontola, golang-nuts
Esko Luontola <esko.l...@gmail.com> writes:

> I'm writing a testing framework for Go (http://github.com/orfjackal/
> gospec) and right now I'm faced with the issue that how object
> equality in Go is defined (or actually, is not defined). Since the ==
> operator is defined only for some of the built-in types, comparing two
> objects for equality is troublesome - it will crash the program.

You may want to look at reflect.DeepEqual. It's not quite as
convenient as == but it is already available.

Ian

Esko Luontola

unread,
Dec 3, 2009, 3:13:19 AM12/3/09
to golang-nuts
inspector_jouve, I also had my doubts and confusion about that, but
since my tests would not pass otherwise, I just had to believe it to
be like that. :) Thanks for the idiom, a switch looks better in this
situation.

Ian, I knew about reflect.DeepEqual, but it won't work in the general
case. For example in the above example DummyStruct has two fields of
which only one is used for equality. With DeepEqual it would not be
possible to ignore fields or have some other special rules for
equality.

Ian Lance Taylor

unread,
Sep 10, 2012, 6:24:05 PM9/10/12
to xiaof...@google.com, golan...@googlegroups.com
On Mon, Sep 10, 2012 at 3:08 PM, <xiaof...@google.com> wrote:
>
> Is there any follow-ups on this? Looks need to write a lot of code for
> configurable equality, which is frequently used.

There is no way to write a custom equality operator for a type, if
that is what you are asking.

As of the Go 1 release structs and arrays support ==.

Ian

Xiaofeng Guo

unread,
Sep 10, 2012, 6:33:23 PM9/10/12
to Ian Lance Taylor, golan...@googlegroups.com
Sure, I know there are "==" and reflect.DeepEquals(), but just feel it may be possible to have partial equality configurable by external users.

Thanks for your reply!

Best Regards,
Xiaofeng

Dan Kortschak

unread,
Sep 10, 2012, 7:00:27 PM9/10/12
to Xiaofeng Guo, Ian Lance Taylor, golan...@googlegroups.com
You can write an Equal() method in the object that takes another object of the same type (concrete or interface) and returns a bool indicating equality. This is more efficient than DeepEqual since it won't depend on reflect.

Xiaofeng Guo

unread,
Sep 10, 2012, 7:05:55 PM9/10/12
to Dan Kortschak, Ian Lance Taylor, golan...@googlegroups.com


And I tries myself, but didn't find a right way. Do you have sample snippet? Thanks!

Best Regards,
Xiaofeng

Jesse McNelis

unread,
Sep 10, 2012, 7:24:19 PM9/10/12
to Xiaofeng Guo, golan...@googlegroups.com
On Tue, Sep 11, 2012 at 9:05 AM, Xiaofeng Guo <xiaof...@google.com> wrote:
> I saw "Equaler" in FAQ doc:
> http://golang.org/doc/go_faq.html#t_and_equal_interface
>
> However, doens't found the usage by cs:
> https://cs.corp.google.com/#search/&q=func.*Equaler%20file:%5C.go&type=cs&m=100
>
> And I tries myself, but didn't find a right way. Do you have sample snippet?
> Thanks!

type A int
func (a A) Equal(b A) bool {
return a==b
}

Using an equaler interface is going to be messy.

type Equaler interface{
Equal(b Equaler) bool
}

type A int
func (a A) Equal(b Equaler) bool {
switch b.(type){ //type switch
case A:
return a==b
default:
return false // b isn't a comparable type to a.
}

--
=====================
http://jessta.id.au

Dan Kortschak

unread,
Sep 10, 2012, 7:30:18 PM9/10/12
to Jesse McNelis, Xiaofeng Guo, golan...@googlegroups.com
Exactly. Though I don't think Equaler interface is actually messy.
Reply all
Reply to author
Forward
0 new messages