My recent involvement with my new side project, go-linq, showed me that type system of Go is not designed for anything near object-oriented programming. There are no generics, no type inheritance, or anything helpful for certain purposes.

However there is a type called interface{} you can assign pretty much anything into it, like object in .NET or Object in Java:

var o interface{} o := 3.14 o := Student{Name:"Ahmet"}

and it does not give any compilation errors. So let’s say you need a function that accepts slices of any type. If you are thinking to do something like:

func Method(in []interface{}){...} ... slice := []int{1,2,3} Method(slice) // gives error

That gives a compilation error, because []int is not an []interface{} . So what’s the solution here? You can require users of Method to convert their slices to []interface{} . Now they have to convert their []AnyType to []interface{} with the help of a function like:

func conv(in []AnyType) (out []interface{}) { out = make([]interface{}, len(in)) for i, v := range in { out[i] = v } return }

But that does not scale. If your user of Method (and this can be a common function like Map , Filter etc.) has N different types they would like to pass to Method , they have to write N conv methods.

What can we do here? Of course, reflection. We will take input as interface{} (which can be of any value) and we will convert it to a slice internally and use it in our Method . How to do that:

func takeSliceArg(arg interface{}) (out []interface{}, ok bool) { slice, success := takeArg(arg, reflect.Slice) if !success { ok = false return } c := slice.Len() out = make([]interface{}, c) for i := 0; i < c; i++ { out[i] = slice.Index(i).Interface() } return out, true } func takeArg(arg interface{}, kind reflect.Kind) (val reflect.Value, ok bool) { val = reflect.ValueOf(arg) if val.Kind() == kind { ok = true } return }

takeArg() function tries to convert value to the specified reflect.Kind and takeSliceArg() function tries to convert a value passed to itself to a slice of interface{} . Although, there’s just a little bit of performance drawback caused by reflection, it is not much.

That’s it. This approach is inspired by Tobia Confronto’s fn project and integrated to go-linq.

This post is written while drunk I don’t take any responsibility about it.