From be052e2c75392ece54a9ca6e783c1944a21e47d5 Mon Sep 17 00:00:00 2001 From: Gregory Eremin Date: Sat, 29 Aug 2015 21:51:12 +0300 Subject: [PATCH] Reflect magic --- demo/demo.go | 5 ++++- secondly.go | 29 +++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/demo/demo.go b/demo/demo.go index b6d0694..f9bc893 100644 --- a/demo/demo.go +++ b/demo/demo.go @@ -4,6 +4,8 @@ import ( "flag" "log" + "github.com/kr/pretty" + "github.com/localhots/secondly" ) @@ -40,8 +42,9 @@ func main() { // Starting a web server secondly.StartServer("", 5500) // Defining callbacks - secondly.OnChange("AppName", func(o, n interface{}) { + secondly.OnChange("app_name", func(o, n interface{}) { log.Printf("OMG! AppName changed from %q to %q", o, n) + pretty.Println(conf) }) // Other application startup logic diff --git a/secondly.go b/secondly.go index e25ea72..a06b0b9 100644 --- a/secondly.go +++ b/secondly.go @@ -39,7 +39,7 @@ func Manage(target interface{}) { panic("Argument must be a pointer to a struct") } - config = target + assign(target) bootstrap() } @@ -109,6 +109,17 @@ func OnChange(field string, fun func(oldVal, newVal interface{})) { callbacks[field] = append(callbacks[field], fun) } +func assign(target interface{}) { + if config == nil { + config = target + return + } + + cval := reflect.ValueOf(config).Elem() + tval := reflect.ValueOf(target).Elem() + cval.Set(tval) +} + func bootstrap() { if configFile == "" { log.Fatalln("path to config file is not set") @@ -136,16 +147,20 @@ func writeConfig() { } func updateConfig(body []byte) { + // Making a copy of old config for further comparison + old := duplicate(config) + // Making a second copy that we will fill with new data dupe := duplicate(config) + if err := json.Unmarshal(body, dupe); err != nil { panic("Failed to update config") return } - defer triggerCallbacks(config, dupe) - // Setting new config - config = dupe + assign(dupe) + + triggerCallbacks(old, dupe) } func marshal(obj interface{}) []byte { @@ -210,7 +225,9 @@ func duplicate(original interface{}) interface{} { // Now we need the type (name) of this struct typ := val.Type() // Creating a duplicate instance of that struct - dupe := reflect.New(typ).Interface() + dupe := reflect.New(typ) + // Value copy + dupe.Elem().Set(val) - return dupe + return dupe.Interface() }