Created
October 31, 2018 05:40
-
-
Save ChristopherThorpe/fd3720efe2ba83c929bf4105719ee967 to your computer and use it in GitHub Desktop.
Nested Map Lookup: find elements in golang maps of arbitrary depth
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NestedMapLookup implementation and usage example | |
// Run it at https://play.golang.org/p/VHRgMcLf0b1 | |
// | |
// JSON is not required, but used to show the example in a "real" setting. | |
// | |
// This gist is copyright (c) 2018 Brightgate Inc. | |
// and licensed under the Creative Commons Attribution 4.0 International license | |
// https://creativecommons.org/licenses/by/4.0/legalcode | |
// | |
package main | |
import ( | |
"fmt" | |
"encoding/json" | |
) | |
var deep = `{ | |
"root": { | |
"internal": { | |
"int": 42, | |
"string": "string", | |
"float64": 6.022e23 | |
} | |
} | |
}` | |
// NestedMapLookup | |
// m: a map from strings to other maps or values, of arbitrary depth | |
// ks: successive keys to reach an internal or leaf node (variadic) | |
// If an internal node is reached, will return the internal map | |
// | |
// Returns: (Exactly one of these will be nil) | |
// rval: the target node (if found) | |
// err: an error created by fmt.Errorf | |
// | |
func NestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}, err error) { | |
var ok bool | |
if len(ks) == 0 { // degenerate input | |
return nil, fmt.Errorf("NestedMapLookup needs at least one key") | |
} | |
if rval, ok = m[ks[0]]; !ok { | |
return nil, fmt.Errorf("key not found; remaining keys: %v", ks) | |
} else if len(ks) == 1 { // we've reached the final key | |
return rval, nil | |
} else if m, ok = rval.(map[string]interface{}); !ok { | |
return nil, fmt.Errorf("malformed structure at %#v", rval) | |
} else { // 1+ more keys | |
return NestedMapLookup(m, ks[1:]...) | |
} | |
} | |
func main() { | |
var m = make(map[string]interface{}) | |
json.Unmarshal([]byte(deep), &m) | |
val, err := NestedMapLookup(m, "root", "internal", "float64") | |
fmt.Printf("(%T) %v\n", val, val) | |
val, err = NestedMapLookup(m, "root", "infernal") | |
fmt.Printf("%v\n", err) | |
} | |
// Expected output: | |
// (float64) 6.022e+23 | |
// key not found; remaining keys: [infernal] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment