Skip to content

Instantly share code, notes, and snippets.

@wingedpig
Created December 13, 2022 15:23
Show Gist options
  • Save wingedpig/a9e4a35990f523d02c2d429a9bca5659 to your computer and use it in GitHub Desktop.
Save wingedpig/a9e4a35990f523d02c2d429a9bca5659 to your computer and use it in GitHub Desktop.
// ReadConfig reads in a JSON-formatted configuration file, looking for any
// include directives, and recursively reading those files as well. Include directives
// are specified as a list keyed on the "Includes" key.
func ReadConfig(filename string, configuration interface{}) error {
// grab any path to the config file to add to the include names
var prefix string
slashindex := strings.LastIndex(filename, "/")
if slashindex != -1 {
prefix = filename[:slashindex+1]
}
file, err := os.Open(filename)
if err != nil {
log.Println("Can't read", filename)
return err
}
decoder := json.NewDecoder(file)
if err := decoder.Decode(configuration); err != nil {
log.Printf("Error in %s\n", filename)
log.Println(err)
return err
}
v := reflect.ValueOf(configuration).Elem()
f := v.FieldByName("Includes")
// make sure that this field is defined, and can be changed.
if !f.IsValid() {
// configuration doesn't have an Includes slice
return nil
}
if f.Kind() != reflect.Slice {
return nil
}
myincludes, ok := f.Interface().([]string)
if !ok {
// configuration doesn't have an Includes slice
return nil
}
// clear out the slice
f.Set(reflect.MakeSlice(f.Type(), 0, f.Cap()))
for _, include := range myincludes {
var incfilename string
if slashindex != -1 {
incfilename = prefix + include
} else {
incfilename = include
}
if err := ReadConfig(incfilename, configuration); err != nil {
return err
}
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment