github.com/l3x/learn-fp-go@v0.0.0-20171228022418-7639825d0b71/3-functional-techniques/ch07-func-param/01_func_param/src/utils/options.go (about) 1 package utils 2 3 import ( 4 "flag" 5 "fmt" 6 "github.com/BurntSushi/toml" 7 "reflect" 8 "strconv" 9 "github.com/pkg/errors" 10 ) 11 12 type Conf struct { 13 Port string `toml:"port"` 14 LogDebugInfo bool `toml:"log_debug_info"` 15 MaxConcurrentConnections int `toml:"max_concurrent_connections"` 16 MaxNumber int `toml:"max_number"` 17 UseNumberHandler bool `toml:"use_number_handler"` 18 } 19 20 var Config Conf 21 22 func GetOptions() bool { 23 var configFile string 24 25 flag.StringVar(&configFile, "config", "", "Configuration file") 26 flag.StringVar(&Config.Port, "port", "8080", "Port that the API listens on") 27 flag.BoolVar(&Config.LogDebugInfo, "log-debug-info", false, "Whether to log debug output to the log (set to true for debug purposes)") 28 flag.IntVar(&Config.MaxConcurrentConnections, "max-concurrent-connections", 6, "Maximum number of concurrent connections (not currently used)") 29 flag.IntVar(&Config.MaxNumber, "max_number", 10, "Maximum number that user is allowed to enter") 30 flag.BoolVar(&Config.UseNumberHandler, "use-number-handler", true, "Use number handler (to display number, optionally with FormatNumber applied) else display files in project root") 31 32 flag.Parse() 33 34 if configFile != "" { 35 if _, err := toml.DecodeFile(configFile, &Config); err != nil { 36 HandlePanic(errors.Wrap(err, "unable to read config file")) 37 } 38 } 39 return true 40 } 41 42 type Datastore interface {} 43 44 func UpdateConfigVal(d Datastore, key, val string) (oldValue string) { 45 Debug.Printf("key (%s), val (%v)\n", key, val) 46 value := reflect.ValueOf(d) 47 if value.Kind() != reflect.Ptr { 48 panic("not a pointer") 49 } 50 valElem := value.Elem() 51 for i := 0; i < valElem.NumField(); i++ { 52 tag := valElem.Type().Field(i).Tag 53 field := valElem.Field(i) 54 switch tag.Get("toml") { 55 case key: 56 if fmt.Sprintf("%v", field.Kind()) == "int" { 57 oldValue = strconv.FormatInt(field.Int(), 10) 58 intVal, err := strconv.Atoi(val) 59 if err != nil { 60 fmt.Printf("could not parse int, key(%s) val(%s)", key, val) 61 } else { 62 field.SetInt(int64(intVal)) 63 } 64 } else if fmt.Sprintf("%v", field.Kind()) == "bool" { 65 oldValue = strconv.FormatBool(field.Bool()) 66 b, err := strconv.ParseBool(val) 67 if err != nil { 68 fmt.Printf("could not parse bool, key(%s) val(%s)", key, val) 69 } else { 70 field.SetBool(b) 71 } 72 } else { 73 // Currently only supports bool, int and string 74 oldValue = field.String() 75 field.SetString(val) 76 } 77 } 78 } 79 return 80 } 81