I admit the syntax is less than ideal (especially with gofmt), but I believe adding two interfaces to an interface definition is equivalent to union:
func myrw(rw interface { io.Reader; io.Writer }) {
rw.Read(nil)
rw.Write(nil)
}
https://play.golang.org/p/D-lJ1pL3MZThat's not a union, that's a product of 2 types. A union is one or the other but not both. You rw here is both a reader and a writer, you can't pass something that is either a reader or a writer, which makes your snippet useless in use-cases where unions are appropriate.
Of course, Go compiler itself uses "unions" with runtime-tricks to implement them. But we're talking about runtime then, not compile time type safety and correctness.
That would be similar to an intersection type (https://www.typescriptlang.org/docs/handbook/advanced-types....), but due to the way Go works, it cannot contain duplicates, and it doesn't work for structs. Union type is "it can be one of these types", and you can then access only fields/methods that all of those types share (unless you cast them of course). The naming can be a bit counter-intuitive.
Especially when you have features like union and intersection types (which Go doesn't have), you can really mold the structure into whatever you need (i.e. to fit whatever data model you're working with), and be very productive without having to come up with weird inheritance hierarchies "just because".
It'd be nice to have the option to explicitly enforce nominal typing in specific places (maybe with its own keyword), but for most cases, structural typing seems good enough so far.