finish config module support ini/json/xml/yaml
Showing
9 changed files
with
742 additions
and
0 deletions
config/config.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | ) | ||
| 6 | |||
| 7 | type ConfigContainer interface { | ||
| 8 | Set(key, val string) error | ||
| 9 | String(key string) string | ||
| 10 | Int(key string) (int, error) | ||
| 11 | Int64(key string) (int64, error) | ||
| 12 | Bool(key string) (bool, error) | ||
| 13 | Float(key string) (float64, error) | ||
| 14 | DIY(key string) (interface{}, error) | ||
| 15 | } | ||
| 16 | |||
| 17 | type Config interface { | ||
| 18 | Parse(key string) (ConfigContainer, error) | ||
| 19 | } | ||
| 20 | |||
| 21 | var adapters = make(map[string]Config) | ||
| 22 | |||
| 23 | // Register makes a config adapter available by the adapter name. | ||
| 24 | // If Register is called twice with the same name or if driver is nil, | ||
| 25 | // it panics. | ||
| 26 | func Register(name string, adapter Config) { | ||
| 27 | if adapter == nil { | ||
| 28 | panic("config: Register adapter is nil") | ||
| 29 | } | ||
| 30 | if _, dup := adapters[name]; dup { | ||
| 31 | panic("config: Register called twice for adapter " + name) | ||
| 32 | } | ||
| 33 | adapters[name] = adapter | ||
| 34 | } | ||
| 35 | |||
| 36 | // config need to be correct JSON as string: {"interval":360} | ||
| 37 | func NewConfig(adapterName, fileaname string) (ConfigContainer, error) { | ||
| 38 | adapter, ok := adapters[adapterName] | ||
| 39 | if !ok { | ||
| 40 | return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName) | ||
| 41 | } | ||
| 42 | return adapter.Parse(fileaname) | ||
| 43 | } |
config/ini.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "bufio" | ||
| 5 | "bytes" | ||
| 6 | "errors" | ||
| 7 | "io" | ||
| 8 | "os" | ||
| 9 | "strconv" | ||
| 10 | "strings" | ||
| 11 | "sync" | ||
| 12 | "unicode" | ||
| 13 | ) | ||
| 14 | |||
| 15 | var ( | ||
| 16 | bComment = []byte{'#'} | ||
| 17 | bEmpty = []byte{} | ||
| 18 | bEqual = []byte{'='} | ||
| 19 | bDQuote = []byte{'"'} | ||
| 20 | ) | ||
| 21 | |||
| 22 | type IniConfig struct { | ||
| 23 | } | ||
| 24 | |||
| 25 | // ParseFile creates a new Config and parses the file configuration from the | ||
| 26 | // named file. | ||
| 27 | func (ini *IniConfig) Parse(name string) (ConfigContainer, error) { | ||
| 28 | file, err := os.Open(name) | ||
| 29 | if err != nil { | ||
| 30 | return nil, err | ||
| 31 | } | ||
| 32 | |||
| 33 | cfg := &IniConfigContainer{ | ||
| 34 | file.Name(), | ||
| 35 | make(map[int][]string), | ||
| 36 | make(map[string]string), | ||
| 37 | make(map[string]int64), | ||
| 38 | sync.RWMutex{}, | ||
| 39 | } | ||
| 40 | cfg.Lock() | ||
| 41 | defer cfg.Unlock() | ||
| 42 | defer file.Close() | ||
| 43 | |||
| 44 | var comment bytes.Buffer | ||
| 45 | buf := bufio.NewReader(file) | ||
| 46 | |||
| 47 | for nComment, off := 0, int64(1); ; { | ||
| 48 | line, _, err := buf.ReadLine() | ||
| 49 | if err == io.EOF { | ||
| 50 | break | ||
| 51 | } | ||
| 52 | if bytes.Equal(line, bEmpty) { | ||
| 53 | continue | ||
| 54 | } | ||
| 55 | |||
| 56 | off += int64(len(line)) | ||
| 57 | |||
| 58 | if bytes.HasPrefix(line, bComment) { | ||
| 59 | line = bytes.TrimLeft(line, "#") | ||
| 60 | line = bytes.TrimLeftFunc(line, unicode.IsSpace) | ||
| 61 | comment.Write(line) | ||
| 62 | comment.WriteByte('\n') | ||
| 63 | continue | ||
| 64 | } | ||
| 65 | if comment.Len() != 0 { | ||
| 66 | cfg.comment[nComment] = []string{comment.String()} | ||
| 67 | comment.Reset() | ||
| 68 | nComment++ | ||
| 69 | } | ||
| 70 | |||
| 71 | val := bytes.SplitN(line, bEqual, 2) | ||
| 72 | if bytes.HasPrefix([]byte(strings.TrimSpace(string(val[1]))), bDQuote) { | ||
| 73 | val[1] = bytes.Trim([]byte(strings.TrimSpace(string(val[1]))), `"`) | ||
| 74 | } | ||
| 75 | |||
| 76 | key := strings.TrimSpace(string(val[0])) | ||
| 77 | cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key) | ||
| 78 | cfg.data[key] = strings.TrimSpace(string(val[1])) | ||
| 79 | cfg.offset[key] = off | ||
| 80 | } | ||
| 81 | return cfg, nil | ||
| 82 | } | ||
| 83 | |||
| 84 | // A Config represents the configuration. | ||
| 85 | type IniConfigContainer struct { | ||
| 86 | filename string | ||
| 87 | comment map[int][]string // id: []{comment, key...}; id 1 is for main comment. | ||
| 88 | data map[string]string // key: value | ||
| 89 | offset map[string]int64 // key: offset; for editing. | ||
| 90 | sync.RWMutex | ||
| 91 | } | ||
| 92 | |||
| 93 | // Bool returns the boolean value for a given key. | ||
| 94 | func (c *IniConfigContainer) Bool(key string) (bool, error) { | ||
| 95 | return strconv.ParseBool(c.data[key]) | ||
| 96 | } | ||
| 97 | |||
| 98 | // Int returns the integer value for a given key. | ||
| 99 | func (c *IniConfigContainer) Int(key string) (int, error) { | ||
| 100 | return strconv.Atoi(c.data[key]) | ||
| 101 | } | ||
| 102 | |||
| 103 | func (c *IniConfigContainer) Int64(key string) (int64, error) { | ||
| 104 | return strconv.ParseInt(c.data[key], 10, 64) | ||
| 105 | } | ||
| 106 | |||
| 107 | // Float returns the float value for a given key. | ||
| 108 | func (c *IniConfigContainer) Float(key string) (float64, error) { | ||
| 109 | return strconv.ParseFloat(c.data[key], 64) | ||
| 110 | } | ||
| 111 | |||
| 112 | // String returns the string value for a given key. | ||
| 113 | func (c *IniConfigContainer) String(key string) string { | ||
| 114 | return c.data[key] | ||
| 115 | } | ||
| 116 | |||
| 117 | // WriteValue writes a new value for key. | ||
| 118 | func (c *IniConfigContainer) Set(key, value string) error { | ||
| 119 | c.Lock() | ||
| 120 | defer c.Unlock() | ||
| 121 | c.data[key] = value | ||
| 122 | return nil | ||
| 123 | } | ||
| 124 | |||
| 125 | func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) { | ||
| 126 | if v, ok := c.data[key]; ok { | ||
| 127 | return v, nil | ||
| 128 | } | ||
| 129 | return v, errors.New("key not find") | ||
| 130 | } | ||
| 131 | |||
| 132 | func init() { | ||
| 133 | Register("ini", &IniConfig{}) | ||
| 134 | } |
config/ini_test.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "os" | ||
| 5 | "testing" | ||
| 6 | ) | ||
| 7 | |||
| 8 | var inicontext = ` | ||
| 9 | appname = beeapi | ||
| 10 | httpport = 8080 | ||
| 11 | mysqlport = 3600 | ||
| 12 | PI = 3.1415976 | ||
| 13 | runmode = "dev" | ||
| 14 | autorender = false | ||
| 15 | copyrequestbody = true | ||
| 16 | ` | ||
| 17 | |||
| 18 | func TestIni(t *testing.T) { | ||
| 19 | f, err := os.Create("testini.conf") | ||
| 20 | if err != nil { | ||
| 21 | t.Fatal(err) | ||
| 22 | } | ||
| 23 | _, err = f.WriteString(inicontext) | ||
| 24 | if err != nil { | ||
| 25 | f.Close() | ||
| 26 | t.Fatal(err) | ||
| 27 | } | ||
| 28 | f.Close() | ||
| 29 | defer os.Remove("testini.conf") | ||
| 30 | iniconf, err := NewConfig("ini", "testini.conf") | ||
| 31 | if err != nil { | ||
| 32 | t.Fatal(err) | ||
| 33 | } | ||
| 34 | if iniconf.String("appname") != "beeapi" { | ||
| 35 | t.Fatal("appname not equal to beeapi") | ||
| 36 | } | ||
| 37 | if port, err := iniconf.Int("httpport"); err != nil || port != 8080 { | ||
| 38 | t.Error(port) | ||
| 39 | t.Fatal(err) | ||
| 40 | } | ||
| 41 | if port, err := iniconf.Int64("mysqlport"); err != nil || port != 3600 { | ||
| 42 | t.Error(port) | ||
| 43 | t.Fatal(err) | ||
| 44 | } | ||
| 45 | if pi, err := iniconf.Float("PI"); err != nil || pi != 3.1415976 { | ||
| 46 | t.Error(pi) | ||
| 47 | t.Fatal(err) | ||
| 48 | } | ||
| 49 | if iniconf.String("runmode") != "dev" { | ||
| 50 | t.Fatal("runmode not equal to dev") | ||
| 51 | } | ||
| 52 | if v, err := iniconf.Bool("autorender"); err != nil || v != false { | ||
| 53 | t.Error(v) | ||
| 54 | t.Fatal(err) | ||
| 55 | } | ||
| 56 | if v, err := iniconf.Bool("copyrequestbody"); err != nil || v != true { | ||
| 57 | t.Error(v) | ||
| 58 | t.Fatal(err) | ||
| 59 | } | ||
| 60 | if err = iniconf.Set("name", "astaxie"); err != nil { | ||
| 61 | t.Fatal(err) | ||
| 62 | } | ||
| 63 | if iniconf.String("name") != "astaxie" { | ||
| 64 | t.Fatal("get name error") | ||
| 65 | } | ||
| 66 | } |
config/json.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "encoding/json" | ||
| 5 | "errors" | ||
| 6 | "io/ioutil" | ||
| 7 | "os" | ||
| 8 | "sync" | ||
| 9 | ) | ||
| 10 | |||
| 11 | type JsonConfig struct { | ||
| 12 | } | ||
| 13 | |||
| 14 | func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { | ||
| 15 | file, err := os.Open(filename) | ||
| 16 | if err != nil { | ||
| 17 | return nil, err | ||
| 18 | } | ||
| 19 | defer file.Close() | ||
| 20 | x := &JsonConfigContainer{ | ||
| 21 | data: make(map[string]interface{}), | ||
| 22 | } | ||
| 23 | content, err := ioutil.ReadAll(file) | ||
| 24 | if err != nil { | ||
| 25 | return nil, err | ||
| 26 | } | ||
| 27 | err = json.Unmarshal(content, &x.data) | ||
| 28 | if err != nil { | ||
| 29 | return nil, err | ||
| 30 | } | ||
| 31 | return x, nil | ||
| 32 | } | ||
| 33 | |||
| 34 | type JsonConfigContainer struct { | ||
| 35 | data map[string]interface{} | ||
| 36 | sync.Mutex | ||
| 37 | } | ||
| 38 | |||
| 39 | func (c *JsonConfigContainer) Bool(key string) (bool, error) { | ||
| 40 | if v, ok := c.data[key].(bool); ok { | ||
| 41 | return v, nil | ||
| 42 | } | ||
| 43 | return false, errors.New("not bool value") | ||
| 44 | } | ||
| 45 | |||
| 46 | func (c *JsonConfigContainer) Int(key string) (int, error) { | ||
| 47 | if v, ok := c.data[key].(float64); ok { | ||
| 48 | return int(v), nil | ||
| 49 | } | ||
| 50 | return 0, errors.New("not int value") | ||
| 51 | } | ||
| 52 | |||
| 53 | func (c *JsonConfigContainer) Int64(key string) (int64, error) { | ||
| 54 | if v, ok := c.data[key].(float64); ok { | ||
| 55 | return int64(v), nil | ||
| 56 | } | ||
| 57 | return 0, errors.New("not bool value") | ||
| 58 | } | ||
| 59 | |||
| 60 | func (c *JsonConfigContainer) Float(key string) (float64, error) { | ||
| 61 | if v, ok := c.data[key].(float64); ok { | ||
| 62 | return v, nil | ||
| 63 | } | ||
| 64 | return 0.0, errors.New("not float64 value") | ||
| 65 | } | ||
| 66 | |||
| 67 | func (c *JsonConfigContainer) String(key string) string { | ||
| 68 | if v, ok := c.data[key].(string); ok { | ||
| 69 | return v | ||
| 70 | } | ||
| 71 | return "" | ||
| 72 | } | ||
| 73 | |||
| 74 | func (c *JsonConfigContainer) Set(key, val string) error { | ||
| 75 | c.Lock() | ||
| 76 | defer c.Unlock() | ||
| 77 | c.data[key] = val | ||
| 78 | return nil | ||
| 79 | } | ||
| 80 | |||
| 81 | func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { | ||
| 82 | if v, ok := c.data[key]; ok { | ||
| 83 | return v, nil | ||
| 84 | } | ||
| 85 | return nil, errors.New("not exist key") | ||
| 86 | } | ||
| 87 | |||
| 88 | func init() { | ||
| 89 | Register("json", &JsonConfig{}) | ||
| 90 | } |
config/json_test.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "os" | ||
| 5 | "testing" | ||
| 6 | ) | ||
| 7 | |||
| 8 | var jsoncontext = `{ | ||
| 9 | "appname": "beeapi", | ||
| 10 | "httpport": 8080, | ||
| 11 | "mysqlport": 3600, | ||
| 12 | "PI": 3.1415976, | ||
| 13 | "runmode": "dev", | ||
| 14 | "autorender": false, | ||
| 15 | "copyrequestbody": true | ||
| 16 | }` | ||
| 17 | |||
| 18 | func TestJson(t *testing.T) { | ||
| 19 | f, err := os.Create("testjson.conf") | ||
| 20 | if err != nil { | ||
| 21 | t.Fatal(err) | ||
| 22 | } | ||
| 23 | _, err = f.WriteString(jsoncontext) | ||
| 24 | if err != nil { | ||
| 25 | f.Close() | ||
| 26 | t.Fatal(err) | ||
| 27 | } | ||
| 28 | f.Close() | ||
| 29 | defer os.Remove("testjson.conf") | ||
| 30 | jsonconf, err := NewConfig("json", "testjson.conf") | ||
| 31 | if err != nil { | ||
| 32 | t.Fatal(err) | ||
| 33 | } | ||
| 34 | if jsonconf.String("appname") != "beeapi" { | ||
| 35 | t.Fatal("appname not equal to beeapi") | ||
| 36 | } | ||
| 37 | if port, err := jsonconf.Int("httpport"); err != nil || port != 8080 { | ||
| 38 | t.Error(port) | ||
| 39 | t.Fatal(err) | ||
| 40 | } | ||
| 41 | if port, err := jsonconf.Int64("mysqlport"); err != nil || port != 3600 { | ||
| 42 | t.Error(port) | ||
| 43 | t.Fatal(err) | ||
| 44 | } | ||
| 45 | if pi, err := jsonconf.Float("PI"); err != nil || pi != 3.1415976 { | ||
| 46 | t.Error(pi) | ||
| 47 | t.Fatal(err) | ||
| 48 | } | ||
| 49 | if jsonconf.String("runmode") != "dev" { | ||
| 50 | t.Fatal("runmode not equal to dev") | ||
| 51 | } | ||
| 52 | if v, err := jsonconf.Bool("autorender"); err != nil || v != false { | ||
| 53 | t.Error(v) | ||
| 54 | t.Fatal(err) | ||
| 55 | } | ||
| 56 | if v, err := jsonconf.Bool("copyrequestbody"); err != nil || v != true { | ||
| 57 | t.Error(v) | ||
| 58 | t.Fatal(err) | ||
| 59 | } | ||
| 60 | if err = jsonconf.Set("name", "astaxie"); err != nil { | ||
| 61 | t.Fatal(err) | ||
| 62 | } | ||
| 63 | if jsonconf.String("name") != "astaxie" { | ||
| 64 | t.Fatal("get name error") | ||
| 65 | } | ||
| 66 | } |
config/xml.go
0 → 100644
| 1 | //xml parse should incluce in <config></config> tags | ||
| 2 | |||
| 3 | package config | ||
| 4 | |||
| 5 | import ( | ||
| 6 | "errors" | ||
| 7 | "github.com/clbanning/x2j" | ||
| 8 | "io/ioutil" | ||
| 9 | "os" | ||
| 10 | "strconv" | ||
| 11 | "sync" | ||
| 12 | ) | ||
| 13 | |||
| 14 | type XMLConfig struct { | ||
| 15 | } | ||
| 16 | |||
| 17 | func (xmls *XMLConfig) Parse(filename string) (ConfigContainer, error) { | ||
| 18 | file, err := os.Open(filename) | ||
| 19 | if err != nil { | ||
| 20 | return nil, err | ||
| 21 | } | ||
| 22 | defer file.Close() | ||
| 23 | x := &XMLConfigContainer{ | ||
| 24 | data: make(map[string]interface{}), | ||
| 25 | } | ||
| 26 | content, err := ioutil.ReadAll(file) | ||
| 27 | if err != nil { | ||
| 28 | return nil, err | ||
| 29 | } | ||
| 30 | d, err := x2j.DocToMap(string(content)) | ||
| 31 | if err != nil { | ||
| 32 | return nil, err | ||
| 33 | } | ||
| 34 | x.data = d["config"].(map[string]interface{}) | ||
| 35 | return x, nil | ||
| 36 | } | ||
| 37 | |||
| 38 | type XMLConfigContainer struct { | ||
| 39 | data map[string]interface{} | ||
| 40 | sync.Mutex | ||
| 41 | } | ||
| 42 | |||
| 43 | func (c *XMLConfigContainer) Bool(key string) (bool, error) { | ||
| 44 | return strconv.ParseBool(c.data[key].(string)) | ||
| 45 | } | ||
| 46 | |||
| 47 | func (c *XMLConfigContainer) Int(key string) (int, error) { | ||
| 48 | return strconv.Atoi(c.data[key].(string)) | ||
| 49 | } | ||
| 50 | |||
| 51 | func (c *XMLConfigContainer) Int64(key string) (int64, error) { | ||
| 52 | return strconv.ParseInt(c.data[key].(string), 10, 64) | ||
| 53 | } | ||
| 54 | |||
| 55 | func (c *XMLConfigContainer) Float(key string) (float64, error) { | ||
| 56 | return strconv.ParseFloat(c.data[key].(string), 64) | ||
| 57 | } | ||
| 58 | |||
| 59 | func (c *XMLConfigContainer) String(key string) string { | ||
| 60 | if v, ok := c.data[key].(string); ok { | ||
| 61 | return v | ||
| 62 | } | ||
| 63 | return "" | ||
| 64 | } | ||
| 65 | |||
| 66 | func (c *XMLConfigContainer) Set(key, val string) error { | ||
| 67 | c.Lock() | ||
| 68 | defer c.Unlock() | ||
| 69 | c.data[key] = val | ||
| 70 | return nil | ||
| 71 | } | ||
| 72 | |||
| 73 | func (c *XMLConfigContainer) DIY(key string) (v interface{}, err error) { | ||
| 74 | if v, ok := c.data[key]; ok { | ||
| 75 | return v, nil | ||
| 76 | } | ||
| 77 | return nil, errors.New("not exist key") | ||
| 78 | } | ||
| 79 | |||
| 80 | func init() { | ||
| 81 | Register("xml", &XMLConfig{}) | ||
| 82 | } |
config/xml_test.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "os" | ||
| 5 | "testing" | ||
| 6 | ) | ||
| 7 | |||
| 8 | //xml parse should incluce in <config></config> tags | ||
| 9 | var xmlcontext = `<?xml version="1.0" encoding="UTF-8"?> | ||
| 10 | <config> | ||
| 11 | <appname>beeapi</appname> | ||
| 12 | <httpport>8080</httpport> | ||
| 13 | <mysqlport>3600</mysqlport> | ||
| 14 | <PI>3.1415976</PI> | ||
| 15 | <runmode>dev</runmode> | ||
| 16 | <autorender>false</autorender> | ||
| 17 | <copyrequestbody>true</copyrequestbody> | ||
| 18 | </config> | ||
| 19 | ` | ||
| 20 | |||
| 21 | func TestXML(t *testing.T) { | ||
| 22 | f, err := os.Create("testxml.conf") | ||
| 23 | if err != nil { | ||
| 24 | t.Fatal(err) | ||
| 25 | } | ||
| 26 | _, err = f.WriteString(xmlcontext) | ||
| 27 | if err != nil { | ||
| 28 | f.Close() | ||
| 29 | t.Fatal(err) | ||
| 30 | } | ||
| 31 | f.Close() | ||
| 32 | defer os.Remove("testxml.conf") | ||
| 33 | xmlconf, err := NewConfig("xml", "testxml.conf") | ||
| 34 | if err != nil { | ||
| 35 | t.Fatal(err) | ||
| 36 | } | ||
| 37 | if xmlconf.String("appname") != "beeapi" { | ||
| 38 | t.Fatal("appname not equal to beeapi") | ||
| 39 | } | ||
| 40 | if port, err := xmlconf.Int("httpport"); err != nil || port != 8080 { | ||
| 41 | t.Error(port) | ||
| 42 | t.Fatal(err) | ||
| 43 | } | ||
| 44 | if port, err := xmlconf.Int64("mysqlport"); err != nil || port != 3600 { | ||
| 45 | t.Error(port) | ||
| 46 | t.Fatal(err) | ||
| 47 | } | ||
| 48 | if pi, err := xmlconf.Float("PI"); err != nil || pi != 3.1415976 { | ||
| 49 | t.Error(pi) | ||
| 50 | t.Fatal(err) | ||
| 51 | } | ||
| 52 | if xmlconf.String("runmode") != "dev" { | ||
| 53 | t.Fatal("runmode not equal to dev") | ||
| 54 | } | ||
| 55 | if v, err := xmlconf.Bool("autorender"); err != nil || v != false { | ||
| 56 | t.Error(v) | ||
| 57 | t.Fatal(err) | ||
| 58 | } | ||
| 59 | if v, err := xmlconf.Bool("copyrequestbody"); err != nil || v != true { | ||
| 60 | t.Error(v) | ||
| 61 | t.Fatal(err) | ||
| 62 | } | ||
| 63 | if err = xmlconf.Set("name", "astaxie"); err != nil { | ||
| 64 | t.Fatal(err) | ||
| 65 | } | ||
| 66 | if xmlconf.String("name") != "astaxie" { | ||
| 67 | t.Fatal("get name error") | ||
| 68 | } | ||
| 69 | } |
config/yaml.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "bytes" | ||
| 5 | "encoding/json" | ||
| 6 | "errors" | ||
| 7 | "github.com/wendal/goyaml2" | ||
| 8 | "io/ioutil" | ||
| 9 | "log" | ||
| 10 | "os" | ||
| 11 | "sync" | ||
| 12 | ) | ||
| 13 | |||
| 14 | type YAMLConfig struct { | ||
| 15 | } | ||
| 16 | |||
| 17 | func (yaml *YAMLConfig) Parse(filename string) (ConfigContainer, error) { | ||
| 18 | y := &YAMLConfigContainer{ | ||
| 19 | data: make(map[string]interface{}), | ||
| 20 | } | ||
| 21 | cnf, err := ReadYmlReader(filename) | ||
| 22 | if err != nil { | ||
| 23 | return nil, err | ||
| 24 | } | ||
| 25 | y.data = cnf | ||
| 26 | return y, nil | ||
| 27 | } | ||
| 28 | |||
| 29 | // 从Reader读取YAML | ||
| 30 | func ReadYmlReader(path string) (cnf map[string]interface{}, err error) { | ||
| 31 | err = nil | ||
| 32 | f, err := os.Open(path) | ||
| 33 | if err != nil { | ||
| 34 | return | ||
| 35 | } | ||
| 36 | defer f.Close() | ||
| 37 | err = nil | ||
| 38 | buf, err := ioutil.ReadAll(f) | ||
| 39 | if err != nil || len(buf) < 3 { | ||
| 40 | return | ||
| 41 | } | ||
| 42 | |||
| 43 | if string(buf[0:1]) == "{" { | ||
| 44 | log.Println("Look lile a Json, try it") | ||
| 45 | err = json.Unmarshal(buf, &cnf) | ||
| 46 | if err == nil { | ||
| 47 | log.Println("It is Json Map") | ||
| 48 | return | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | _map, _err := goyaml2.Read(bytes.NewBuffer(buf)) | ||
| 53 | if _err != nil { | ||
| 54 | log.Println("Goyaml2 ERR>", string(buf), _err) | ||
| 55 | //err = goyaml.Unmarshal(buf, &cnf) | ||
| 56 | err = _err | ||
| 57 | return | ||
| 58 | } | ||
| 59 | if _map == nil { | ||
| 60 | log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf)) | ||
| 61 | } | ||
| 62 | cnf, ok := _map.(map[string]interface{}) | ||
| 63 | if !ok { | ||
| 64 | log.Println("Not a Map? >> ", string(buf), _map) | ||
| 65 | cnf = nil | ||
| 66 | } | ||
| 67 | return | ||
| 68 | } | ||
| 69 | |||
| 70 | type YAMLConfigContainer struct { | ||
| 71 | data map[string]interface{} | ||
| 72 | sync.Mutex | ||
| 73 | } | ||
| 74 | |||
| 75 | func (c *YAMLConfigContainer) Bool(key string) (bool, error) { | ||
| 76 | if v, ok := c.data[key].(bool); ok { | ||
| 77 | return v, nil | ||
| 78 | } | ||
| 79 | return false, errors.New("not bool value") | ||
| 80 | } | ||
| 81 | |||
| 82 | func (c *YAMLConfigContainer) Int(key string) (int, error) { | ||
| 83 | if v, ok := c.data[key].(int); ok { | ||
| 84 | return v, nil | ||
| 85 | } | ||
| 86 | return 0, errors.New("not int value") | ||
| 87 | } | ||
| 88 | |||
| 89 | func (c *YAMLConfigContainer) Int64(key string) (int64, error) { | ||
| 90 | if v, ok := c.data[key].(int64); ok { | ||
| 91 | return v, nil | ||
| 92 | } | ||
| 93 | return 0, errors.New("not bool value") | ||
| 94 | } | ||
| 95 | |||
| 96 | func (c *YAMLConfigContainer) Float(key string) (float64, error) { | ||
| 97 | if v, ok := c.data[key].(float64); ok { | ||
| 98 | return v, nil | ||
| 99 | } | ||
| 100 | return 0.0, errors.New("not float64 value") | ||
| 101 | } | ||
| 102 | |||
| 103 | func (c *YAMLConfigContainer) String(key string) string { | ||
| 104 | if v, ok := c.data[key].(string); ok { | ||
| 105 | return v | ||
| 106 | } | ||
| 107 | return "" | ||
| 108 | } | ||
| 109 | |||
| 110 | func (c *YAMLConfigContainer) Set(key, val string) error { | ||
| 111 | c.Lock() | ||
| 112 | defer c.Unlock() | ||
| 113 | c.data[key] = val | ||
| 114 | return nil | ||
| 115 | } | ||
| 116 | |||
| 117 | func (c *YAMLConfigContainer) DIY(key string) (v interface{}, err error) { | ||
| 118 | if v, ok := c.data[key]; ok { | ||
| 119 | return v, nil | ||
| 120 | } | ||
| 121 | return nil, errors.New("not exist key") | ||
| 122 | } | ||
| 123 | |||
| 124 | func init() { | ||
| 125 | Register("yaml", &YAMLConfig{}) | ||
| 126 | } |
config/yaml_tast.go
0 → 100644
| 1 | package config | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "os" | ||
| 5 | "testing" | ||
| 6 | ) | ||
| 7 | |||
| 8 | var yamlcontext = ` | ||
| 9 | "appname": "beeapi", | ||
| 10 | "httpport": 8080, | ||
| 11 | "mysqlport": 3600, | ||
| 12 | "PI": 3.1415976, | ||
| 13 | "runmode": "dev", | ||
| 14 | "autorender": false, | ||
| 15 | "copyrequestbody": true | ||
| 16 | ` | ||
| 17 | |||
| 18 | func TestYaml(t *testing.T) { | ||
| 19 | f, err := os.Create("testyaml.conf") | ||
| 20 | if err != nil { | ||
| 21 | t.Fatal(err) | ||
| 22 | } | ||
| 23 | _, err = f.WriteString(yamlcontext) | ||
| 24 | if err != nil { | ||
| 25 | f.Close() | ||
| 26 | t.Fatal(err) | ||
| 27 | } | ||
| 28 | f.Close() | ||
| 29 | defer os.Remove("testyaml.conf") | ||
| 30 | yamlconf, err := NewConfig("yaml", "testyaml.conf") | ||
| 31 | if err != nil { | ||
| 32 | t.Fatal(err) | ||
| 33 | } | ||
| 34 | if yamlconf.String("appname") != "beeapi" { | ||
| 35 | t.Fatal("appname not equal to beeapi") | ||
| 36 | } | ||
| 37 | if port, err := yamlconf.Int("httpport"); err != nil || port != 8080 { | ||
| 38 | t.Error(port) | ||
| 39 | t.Fatal(err) | ||
| 40 | } | ||
| 41 | if port, err := yamlconf.Int64("mysqlport"); err != nil || port != 3600 { | ||
| 42 | t.Error(port) | ||
| 43 | t.Fatal(err) | ||
| 44 | } | ||
| 45 | if pi, err := yamlconf.Float("PI"); err != nil || pi != 3.1415976 { | ||
| 46 | t.Error(pi) | ||
| 47 | t.Fatal(err) | ||
| 48 | } | ||
| 49 | if yamlconf.String("runmode") != "dev" { | ||
| 50 | t.Fatal("runmode not equal to dev") | ||
| 51 | } | ||
| 52 | if v, err := yamlconf.Bool("autorender"); err != nil || v != false { | ||
| 53 | t.Error(v) | ||
| 54 | t.Fatal(err) | ||
| 55 | } | ||
| 56 | if v, err := yamlconf.Bool("copyrequestbody"); err != nil || v != true { | ||
| 57 | t.Error(v) | ||
| 58 | t.Fatal(err) | ||
| 59 | } | ||
| 60 | if err = yamlconf.Set("name", "astaxie"); err != nil { | ||
| 61 | t.Fatal(err) | ||
| 62 | } | ||
| 63 | if yamlconf.String("name") != "astaxie" { | ||
| 64 | t.Fatal("get name error") | ||
| 65 | } | ||
| 66 | } |
-
Please register or sign in to post a comment