This is really neat! I've always liked LINQ, it's nice to see it pop up in Go. I wonder if there's a way to fix the reflection related performance penalty, 5-10x seems like a lot.
I've been thinking about this a bit recently, I think the best way to a functional style in Go is to use concrete types instead. Other approaches you could use here to avoid using empty interface:
Use go generate to generate the code against specific types of your own, but this requires maintenance and means generating a lot of code (fiddly)
Use slices of interfaces defining the behaviour containers require - this is slow and requires copying slices in order to convert the interface type to your concrete type.
Write only the functions you need against a specific slice of types or type
So to avoid the problems above I think it is better to use functions that act on a specific type (or functions attached to a slice of a type, as often these are functions acting on a collection). Yes this means your beautiful abstract functions can't be applied to any type of data, but it is faster, clearer, avoids typing casts everywhere, and let's you get really specific with the behaviour, as you're no longer trying to write general functions and can include only those you use.
I tend to define collections on slices of types that I use a lot (for example to add Contains, Map or Filter to a slice of strings type StringSlice []string ), and then use them everywhere in place of just a normal slice, to get the specific behaviour.
This is really neat! I've always liked LINQ, it's nice to see it pop up in Go. I wonder if there's a way to fix the reflection related performance penalty, 5-10x seems like a lot.
I've been thinking about this a bit recently, I think the best way to a functional style in Go is to use concrete types instead. Other approaches you could use here to avoid using empty interface: