Go proposal: Compare IP subnets

Part of the Accepted! series, explaining the upcoming Go changes in simple terms.

Compare IP address prefixes the same way IANA does.

Ver. 1.26 • Stdlib • Low impact

Summary

An IP address prefix represents a IP subnet. These prefixes are usually written in CIDR notation:

10.0.0.0/8
127.0.0.0/8
169.254.0.0/16
203.0.113.0/24

In Go, an IP prefix is represented by the netip.Prefix type.

The new Prefix.Compare method lets you compare two IP prefixes, making it easy to sort them without having to write your own comparison code. The imposed order matches both Python's implementation and the assumed order from IANA.

Motivation

When the Go team initially designed the IP subnet type (net/netip.Prefix), they chose not to add a Compare method because there wasn't a widely accepted way to order these values.

Because of this, if a developer needs to sort IP subnets — for example, to organize routing tables or run tests — they have to write their own comparison logic. This results in repetitive and error-prone code.

The proposal aims to provide a standard way to compare IP prefixes. This should reduce boilerplate code and help programs sort IP subnets consistently.

Description

Add the Compare method to the netip.Prefix type:

// Compare returns an integer comparing two prefixes.
// The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2.
func (p Prefix) Compare(p2 Prefix) int

Compare orders two prefixes as follows:

  • First by validity (invalid before valid).
  • Then by address family (IPv4 before IPv6).
    10.0.0.0/8 < ::/8
  • Then by masked IP address (network IP).
    10.0.0.0/8 < 10.0.1.0/8
  • Then by prefix length.
    10.0.0.0/8 < 10.0.0.0/16
  • Then by unmasked address (original IP).
    10.0.0.0/8 < 10.0.0.1/8

This follows the same order as Python's netaddr.IPNetwork and the standard IANA convention.

Example

Sort a list of IP prefixes:

prefixes := []netip.Prefix{
    netip.MustParsePrefix("10.0.1.0/8"),
    netip.MustParsePrefix("203.0.113.0/24"),
    netip.MustParsePrefix("10.0.0.0/8"),
    netip.MustParsePrefix("169.254.0.0/16"),
    netip.MustParsePrefix("203.0.113.0/8"),
}

slices.SortFunc(prefixes, func(a, b netip.Prefix) int {
    return a.Compare(b)
})

for _, p := range prefixes {
    fmt.Println(p.String())
}
10.0.0.0/8
10.0.1.0/8
169.254.0.0/16
203.0.113.0/8
203.0.113.0/24

Further reading

𝗣 61642 • 𝗖𝗟 700355

★ Subscribe to keep up with new posts.