improve error handling
diff --git a/gcfg.go b/gcfg.go
index e0b8f8a..4c63cf2 100644
--- a/gcfg.go
+++ b/gcfg.go
@@ -49,7 +49,6 @@
// - writing gcfg files
// - error handling
// - include error context
-// - avoid reflection-related panics
// - more helpful error messages
// - error types / codes?
// - limit input size?
@@ -110,6 +109,9 @@
func set(cfg interface{}, sect, sub, name, value string) error {
vDest := reflect.ValueOf(cfg).Elem()
vSect := fieldFold(vDest, sect)
+ if !vSect.IsValid() {
+ return fmt.Errorf("no corresponding field: section %q", sect)
+ }
if vSect.Kind() == reflect.Map {
if vSect.IsNil() {
vSect.Set(reflect.MakeMap(vSect.Type()))
@@ -123,9 +125,13 @@
}
vSect = pv.Elem()
} else if sub != "" {
- return fmt.Errorf("expected map; section %q subsection %q", sect, sub)
+ return fmt.Errorf("corresponding field should be a map: "+
+ "section %q subsection %q", sect, sub)
}
vName := fieldFold(vSect, name)
+ if !vName.IsValid() {
+ return fmt.Errorf("no corresponding field: name %q", name)
+ }
vAddr := vName.Addr().Interface()
switch v := vAddr.(type) {
case *string:
diff --git a/gcfg_test.go b/gcfg_test.go
index 68cdff8..6a7ff5c 100644
--- a/gcfg_test.go
+++ b/gcfg_test.go
@@ -98,13 +98,16 @@
{"\n[section]\n=", &conf01{}, false},
// error: line too long
{"[section]\nname=value\n" + sp4096, &conf01{}, false},
- // #50
// error: no section
{"name=value", &conf01{}, false},
// error: failed to parse
{"\n[section]\nbool=maybe", &conf02{sect02{}}, false},
// error: empty subsection
{"\n[sub \"\"]\nname=value", &conf04{}, false},
+ // error: section name not matched
+ {"\n[nonexistent]\nname=value", &conf01{}, false},
+ // error: variable name not matched
+ {"\n[section]\nnonexistent=value", &conf01{}, false},
}},
}