I agree that list comprehensions aren't any easier to read. A proper streaming interface on the other hand lets you easily follow how the data is transformed:
As an aside, Go conflating lists and views irks me, in part due to what weird semantics it gives to append (e.g. if you have two disjunct slices and append an element to one slice, that might modify the other slice).
The problem with this is that people again get way to clever with it. it's not just stream -> filter -> collection, there will be a bunch of groupbys in there etc. If you have to debug or extend the functionality it's a nightmare to understand what all the intermediate representations are
Inspecting intermediate representations is trivial by just collecting them into a variable?
More complicated scenarios are exactly what streaming APIs excel at, by treating each step as a single transformation of data. Lack of a proper group by function is one of my classic examples for how Go forces you into an imperative style that's harder to understand at a glance.
You could write your own syntax sugar functions with signatures like...
func copyArrStringShallow(x []string) []string { return x }
// strings are immutable in go, but for []byte etc also deep copy that.
func copyArrStringDeep(x []string) []string {
ret := make([]string, 0, len(x))
copy(ret, x)
return ret
}