Skip to content

Instantly share code, notes, and snippets.

@ParthDesai
Last active September 3, 2021 09:54
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ParthDesai/5e0f1d4725a644f1e632 to your computer and use it in GitHub Desktop.
Save ParthDesai/5e0f1d4725a644f1e632 to your computer and use it in GitHub Desktop.
Generic map function in golang
package main
import (
"fmt"
"reflect"
)
func main() {
r := genericMap([]int{1, 2, 3, 4}, func(x int) string {
return "Hello"
})
fmt.Println(r)
}
func genericMap(arr interface{}, mapFunc interface{}) interface{} {
funcValue := reflect.ValueOf(mapFunc)
arrValue := reflect.ValueOf(arr)
// Retrieve the type, and check if it is one of the array or slice.
arrType := arrValue.Type()
arrElemType := arrType.Elem()
if arrType.Kind() != reflect.Array && arrType.Kind() != reflect.Slice {
panic("Array parameter's type is neither array nor slice.")
}
funcType := funcValue.Type()
// Checking whether the second argument is function or not.
// And also checking whether its signature is func ({type A}) {type B}.
if funcType.Kind() != reflect.Func || funcType.NumIn() != 1 || funcType.NumOut() != 1 {
panic("Second argument must be map function.")
}
// Checking whether element type is convertible to function's first argument's type.
if !arrElemType.ConvertibleTo(funcType.In(0)) {
panic("Map function's argument is not compatible with type of array.")
}
// Get slice type corresponding to function's return value's type.
resultSliceType := reflect.SliceOf(funcType.Out(0))
// MakeSlice takes a slice kind type, and makes a slice.
resultSlice := reflect.MakeSlice(resultSliceType, 0, arrValue.Len())
for i := 0; i < arrValue.Len(); i++ {
resultSlice = reflect.Append(resultSlice, funcValue.Call([]reflect.Value{arrValue.Index(i)})[0])
}
// Convering resulting slice back to generic interface.
return resultSlice.Interface()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment