mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 15:00:54 +00:00
commit
d9e4836715
@ -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
|
||||
|
@ -652,3 +652,83 @@ 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)
|
||||
|
||||
|
||||
if storedVal.IsValid() {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
@ -244,3 +244,80 @@ func TestParseFormTag(t *testing.T) {
|
||||
t.Errorf("Form Tag that should be ignored was not correctly parsed.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapGet(t *testing.T) {
|
||||
// test one level map
|
||||
m1 := map[string]int64{
|
||||
"a": 1,
|
||||
"1": 2,
|
||||
}
|
||||
|
||||
if res, err := MapGet(m1, "a"); err == nil {
|
||||
if res.(int64) != 1 {
|
||||
t.Errorf("Should return 1, but return %v", res)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error happens %v", err)
|
||||
}
|
||||
|
||||
if res, err := MapGet(m1, "1"); err == nil {
|
||||
if res.(int64) != 2 {
|
||||
t.Errorf("Should return 2, but return %v", res)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error happens %v", err)
|
||||
}
|
||||
|
||||
if res, err := MapGet(m1, 1); err == nil {
|
||||
if res.(int64) != 2 {
|
||||
t.Errorf("Should return 2, but return %v", res)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error happens %v", err)
|
||||
}
|
||||
|
||||
// test 2 level map
|
||||
m2 := map[string]interface{}{
|
||||
"1": map[string]float64{
|
||||
"2": 3.5,
|
||||
},
|
||||
}
|
||||
|
||||
if res, err := MapGet(m2, 1, 2); err == nil {
|
||||
if res.(float64) != 3.5 {
|
||||
t.Errorf("Should return 3.5, but return %v", res)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error happens %v", err)
|
||||
}
|
||||
|
||||
// test 5 level map
|
||||
m5 := map[string]interface{}{
|
||||
"1": map[string]interface{}{
|
||||
"2": map[string]interface{}{
|
||||
"3": map[string]interface{}{
|
||||
"4": map[string]interface{}{
|
||||
"5": 1.2,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if res, err := MapGet(m5, 1, 2, 3, 4, 5); err == nil {
|
||||
if res.(float64) != 1.2 {
|
||||
t.Errorf("Should return 1.2, but return %v", res)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error happens %v", err)
|
||||
}
|
||||
|
||||
// check whether element not exists in map
|
||||
if res, err := MapGet(m5, 5, 4, 3, 2, 1); err == nil {
|
||||
if res != nil {
|
||||
t.Errorf("Should return nil, but return %v", res)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("Error happens %v", err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user