There's no amount of union types that will save you if you want to write a polymorphic, type safe map/filter/reduce function. These functions need to be generic over containers.
At best, with this union type hack what you'll recover is similar to "ad hoc" polymorphism, not true parametric polymorphism.
For example, you could declare a function as Foo(thing string | []int). In other to use "thing" you'd need to do a type assertion. That'd allow "generic" functions where the author could decide which types to support, without going all the way to generics, which tend to open a few cans of worms. Same thing for structs and such. Obviously this has an impact on internal layouts; union values would need an internal type tag similar to interfaces.
With this in mind, I would hope that Go could get better pattern matching with destructuring; switch statements currently only allow you to extract one value, and it's confusing that a single name is shared between all cases. But I'd love to be able to do something like:
or whatever.If we could get proper Rust-style enums on top of that (with appropriate pattern matching) that'd also be neat.