Comparison operators, part IV

February 15, 2024

Comparison operators

  • Struct types are comparable if all their field types are comparable. Two struct values are equal if their corresponding non-blank field values are equal. The fields are compared in source order, and comparison stops as soon as two field values differ (or all fields have been compared).

I think this is clear. But it leads to some interesting things in the wild, when you want structs to not be comparable. I’ve talked about this before, but to make structs non-comparable, an easy approach is to include a blank field!

type Snowflake struct {
	ID int
	_  string
}

Of course this has the problem that a string takes up memory. And if you have many of these structs in use, you’ll be wasting a lot of memory just for the sake of a non-comparability. What can you do? You can use a data type that uses no memory! Some common options: struct{} or a zero-length array.

type Snowflake struct {
	ID
	_ [0]int
}
  • Array types are comparable if their array element types are comparable. Two array values are equal if their corresponding element values are equal. The elements are compared in ascending index order, and comparison stops as soon as two element values differ (or all elements have been compared).

Simple enough.

  • Type parameters are comparable if they are strictly comparable (see below).

Well that’s the end of our tidy list of type comparison rules. Now for some nitty-gritty details, before we get back to what strictly comparable means, as mentioned in the last sentence.

A comparison of two interface values with identical dynamic types causes a run-time panic if that type is not comparable. This behavior applies not only to direct interface value comparisons but also when comparing arrays of interface values or structs with interface-valued fields.

Oh, that sounds fun. Let’s make that happen:

var a any = func() {}
var b any = func() {}
fmt.Println(a == b) // panic: runtime error: comparing uncomparable type func()

And likewise:

type X struct {
  F func()
}
var a any = X{}
var b any = X{}
fmt.Println(a == b)
fmt.Println(a == b) // panic: runtime error: comparing uncomparable type main.X

Quotes from The Go Programming Language Specification Version of August 2, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Get daily content like this in your inbox!

Subscribe