In Go generics, why can't I use comparable constraint with order operators?

Issue

I am exploring go generics (1.18 beta), and have questions related to comparing two numerical values (a simple method that takes two values and returns a greater number).

For that, I am creating a custom numeric type that covers this type set (in the function getBiggerNumber):

int | int8 | int16 | int32 | int64 | float32 | float64

However, added one more function but this time instead of using a custom type had used a comparable built-in constraint (in the function getBiggerNumberWithComparable).

But below code gives an error on this method as

"invalid operation: cannot compare t1 > t2 (operator > not defined on T)"?

Any idea why the > operation did not work on built-in comparable types?

package main

import "fmt"

type numbers interface {
    int | int8 | int16 | int32 | int64 | float32 | float64
}

func getBiggerNumber[T numbers](t1, t2 T) T {
    if t1 > t2 {
        return t1
    }
    return t2
}

func getBiggerNumberWithComparable[T comparable](t1, t2 T) T {
    if t1 > t2 { // ./generics-sample.go:17:5: invalid operation: cannot compare t1 > t2 (operator > not defined on T)
        return t1
    }
    return t2
}

func main() {
    fmt.Println(getBiggerNumber(2.5, -4.0)) 
    fmt.Println(getBiggerNumberWithComparable(2.5, -4.0))
}

Solution

comparable is the constraint for types that support equality operators == and !=. The language spec defines this in Type constraints.

Notably, this includes anything that can be used as a map key, including arrays, structs with comparable fields but not interfaces.

It is true that in the Go language specifications, the comparison operators include order operators as (<, >, <=, >=). This choice of terminology probably is what confuses you. However the specs also disambiguate:

The equality operators == and != apply to operands that are comparable. The ordering operators <, <=, >, and >= apply to operands that are ordered.

In Go 1.18 the available constraint that supports the order operators such as > and < is constraints.Ordered1:

type Ordered interface {
    Integer | Float | ~string
}

1: note that the package golang.org/x/exp is experimental. Its contents aren’t guaranteed to be backwards compatible with new Go releases, but you can always copy-paste the definitions you need into your own code

Answered By – blackgreen

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.