I started learning Go a few months ago and am trying to shake the rust off after a project took me out of the Go world for several weeks. I'd appreciate a code review on this flood fill algorithm I wrote for practice.Specifically I'm looking for points on any code I've written that is unidiomatic in Go, and of course any glaring mistakes that my manual testing didn't catch. Performance is a more minor concern. I'm sure I can tell each node where it came from to improve performance by ~25%, but that's more trouble than it's worth for a little practice code.package filltype OrderedPair struct {    x, y int}var wg sync.WaitGroupfunc FloodFill(graph [][]int, origin OrderedPair) []OrderedPair {    val := graph[origin.y][origin.x]    length := 0    for _, row := range graph {        length += len(row)    }    q := make(chan OrderedPair, length)    q <- origin    seen := make(map[OrderedPair]struct{})    for {        select {        case op := <-q:            if _, found := seen[op]; found {                continue            } else {                seen[op] = struct{}{}            }            wg.Add(4)            for _, mods := range [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} {                go func(xmod, ymod int) {                    newx := op.x + xmod                    newy := op.y + ymod                    if 0 <= newy && newy < len(graph) && 0 <= newx && newx < len(graph[newy]) {                        if graph[newy][newx] == val {                            q <- OrderedPair{newx, newy}                        }                    }                    wg.Done()                }(mods[0], mods[1])            }            wg.Wait()        default:            result := make([]OrderedPair, 0, len(seen))            for key := range seen {                result = append(result, key)            }            return result        }    }}Particularly I'm not a big fan of thefor {    select {    case DO SOMETHING:        // ...    default:        // wrap up the function and return    }}I would much rather my default case break me out of the infinite loop so I handle the cleanup and return on the parent level, but it seems a break in a select statement just breaks the select. Any better way to handle that?I'd also like to generalize the function if possible. Since I'm not using any sort of fuzzy-match and I'm giving back []OrderedPair regardless, I should be able to operate on a graph [][]interface{} but the mechanics of that aren't clear to me (I can't pass in a concrete [][]int or [][]string anymore. Do I have to go through the reflect package? That seems like a pain, but might be out of scope for CR)
Golang Flood Fill
go;graphics