From d4e15c0bd0d27c5ed4f49d150e1972af9a58d6bb Mon Sep 17 00:00:00 2001 From: Sergey Shcherbina Date: Mon, 17 Aug 2015 00:08:02 +0500 Subject: [PATCH] Added MapGet template func --- template.go | 1 + templatefunc.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/template.go b/template.go index 64b1939e..905f0bef 100644 --- a/template.go +++ b/template.go @@ -54,6 +54,7 @@ func init() { beegoTplFuncMap["assets_js"] = AssetsJs beegoTplFuncMap["assets_css"] = AssetsCss beegoTplFuncMap["config"] = Config + beegoTplFuncMap["map_get"] = MapGet // go1.2 added template funcs // Comparisons diff --git a/templatefunc.go b/templatefunc.go index 28ed15a3..6092f71e 100644 --- a/templatefunc.go +++ b/templatefunc.go @@ -652,3 +652,76 @@ func ge(arg1, arg2 interface{}) (bool, error) { } // go1.2 added template funcs. end + +// getting value from map by keys +// usage: +// Data["m"] = map[string]interface{} { +// "a": 1, +// "1": map[string]float64{ +// "c": 4, +// }, +// } +// +// {{ map_get m "a" }} // return 1 +// {{ map_get m 1 "c" }} // return 4 +func MapGet(arg1 interface{}, arg2 ...interface{}) (interface{}, error) { + arg1Type := reflect.TypeOf(arg1) + arg1Val := reflect.ValueOf(arg1) + + if arg1Type.Kind() == reflect.Map && len(arg2) > 0 { + // check whether arg2[0] type equals to arg1 key type + // if they are different, make convertion + arg2Val := reflect.ValueOf(arg2[0]) + arg2Type := reflect.TypeOf(arg2[0]) + if arg2Type.Kind() != arg1Type.Key().Kind() { + // convert arg2Value to string + var arg2ConvertedVal interface{} + arg2String := fmt.Sprintf("%v", arg2[0]) + + // convert string representation to any other type + switch arg1Type.Key().Kind() { + case reflect.Bool: + arg2ConvertedVal, _ = strconv.ParseBool(arg2String) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + arg2ConvertedVal, _ = strconv.ParseInt(arg2String, 0, 64) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + arg2ConvertedVal, _ = strconv.ParseUint(arg2String, 0, 64) + case reflect.Float32, reflect.Float64: + arg2ConvertedVal, _ = strconv.ParseFloat(arg2String, 64) + case reflect.String: + arg2ConvertedVal = arg2String + default: + arg2ConvertedVal = arg2Val.Interface() + } + arg2Val = reflect.ValueOf(arg2ConvertedVal) + } + + storedVal := arg1Val.MapIndex(arg2Val) + + var result interface{} + + switch arg1Type.Elem().Kind() { + case reflect.Bool: + result = storedVal.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + result = storedVal.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + result = storedVal.Uint() + case reflect.Float32, reflect.Float64: + result = storedVal.Float() + case reflect.String: + result = storedVal.String() + default: + result = storedVal.Interface() + } + + // if there is more keys, handle this recursively + if len(arg2) > 1 { + return MapGet(result, arg2[1:]...) + } else { + return result, nil + } + } else { + return nil, nil + } +}