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