Skip to content

Instantly share code, notes, and snippets.

@tsujeeth
Created December 5, 2014 16:51
Show Gist options
  • Save tsujeeth/a30aa3e70bcca18a546a to your computer and use it in GitHub Desktop.
Save tsujeeth/a30aa3e70bcca18a546a to your computer and use it in GitHub Desktop.
Using Golang's reflect package (MakeFunc) to implement typed accessors for a map.
/* Using reflect.MakeFunc to fetch from map[string]interface{}.
* getString(key) will either return the 'string' value or empty string.
* getInt(key) will either return the 'int' value or a 0.
*/
package main
import (
"fmt"
"reflect"
)
var record map[string]interface{}
func init() {
record = map[string]interface{}{
"name": "urx",
"number": 168,
}
}
func get(in []reflect.Value, retType reflect.Type) ([]reflect.Value) {
m := in[0]
key := in[1]
result := m.MapIndex(key)
ok := false
if result.IsValid() == false {
return []reflect.Value{reflect.Zero(retType), reflect.ValueOf(ok)}
}
resultval := result.Interface()
if retType != reflect.TypeOf(resultval) {
return []reflect.Value{reflect.Zero(retType), reflect.ValueOf(ok)}
}
ok = true
return []reflect.Value{reflect.ValueOf(resultval), reflect.ValueOf(ok)}
}
func MakeFuncStub(typ reflect.Type, fn func(args []reflect.Value, retType reflect.Type) (results []reflect.Value)) reflect.Value {
retType := typ.Out(0)
return reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
return fn(args, retType)
})
}
func main() {
makeGet := func(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
fn.Set(MakeFuncStub(fn.Type(), get))
}
var getInt func(map[string]interface{}, string) (int, bool)
makeGet(&getInt)
var getString func(map[string]interface{}, string) (string, bool)
makeGet(&getString)
v1, ok := getInt(record, "number")
fmt.Printf("%v, %v\n", v1, ok)
v2, ok := getString(record, "doesnotexist")
fmt.Printf("%v, %v\n", v2, ok)
v3, ok := getString(record, "number")
fmt.Printf("%v, %v\n", v3, ok)
v4, ok := getString(record, "name")
fmt.Printf("%v, %v\n", v4, ok)
v5, ok := getInt(record, "nonum")
fmt.Printf("%v, %v\n", v5, ok)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment