trouble sorting with generics

101 views
Skip to first unread message

Jason E. Aten

unread,
Aug 9, 2025, 6:45:55 PMAug 9
to golang-nuts
I'm trying to use generics to display a map contents, sorted by key.

It is not going well.

Here is the (minimized/extracted) code I am using:


I'm staring at the following crash dump from a red test. Notice the
node list is not sorted, but random: (the project is a distributed
system that maintains a cluster membership list; here a test for removing
a node from the cluster is failing...)

panic: expected 'node_7' to be gone! membership after SingleUpdateClusterMemberConfig; memlistAfterRemove = 'memMap of len(8):

           node_6

           node_5

           node_1

           node_0

           node_4

           node_3

           node_7

           node_2

        '; nodes[7].PeerID = 'oXs3x5peQ2EOt1esGrOM0axFQO2x'

However, the string that generated that list TRIED TO SORT IT. That code looks like this:

 _, present := memlistAfterRemove[nodes[i].PeerID]

 if present {

   panic(fmt.Sprintf("expected '%v' to be gone! membership after SingleUpdateClusterMemberConfig; memlistAfterRemove = '%v'; nodes[%v].PeerID = '%v'", namei, memlistAfterRemove, i, nodes[i].PeerID))

 }

and the sorting code is exactly the String() code shown in the playgound link above ( https://go.dev/play/p/_GpoXKp9kER )

The mystery is: why didn't the node list come out sorted?

Any thoughts?

Thanks!

- Jason

code in case playground not available:


package main

import (
"cmp"
"fmt"
"iter"
"slices"
)

// sort any map by its keys
func sorted[K cmp.Ordered, V any](m map[K]V) iter.Seq2[K, V] {

return func(yield func(K, V) bool) {

var keys []K
for k := range m {
keys = append(keys, k)
}
slices.Sort(keys)
for _, k := range keys {
v := m[k]
if !yield(k, v) {
return
}
}
} // end seq2 definition
}

type memMap map[string]string

func (m memMap) String() (r string) {
r = fmt.Sprintf("memMap of len(%v):\n", len(m))
for key := range sorted(m) {
r += fmt.Sprintf("   %v\n", key)
}
return
}

func main() {
m := make(memMap)
m["node_2"] = "2"
m["node_1"] = "1"
m["node_0"] = "0"
m["node_9"] = "9"

fmt.Printf("%v\n", m)
fmt.Printf("%v\n", m)
fmt.Printf("%v\n", m)
}


Jason E. Aten

unread,
Aug 9, 2025, 6:51:10 PMAug 9
to golang-nuts
Not that it should be relevant, but this was running under testing/synctest as well... 
go version go1.25rc2 darwin/amd64

Jason E. Aten

unread,
Aug 9, 2025, 7:18:06 PMAug 9
to golang-nuts
I ruled out testing/synctest: still happens without it.

Ah: nevermind! I figured out my bug. I was printing out the short "node name" when
in reality the sort was on a random long node identifier, which was then not what was displayed.

Reply all
Reply to author
Forward
0 new messages