mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 15:10:55 +00:00
finish config module support ini/json/xml/yaml
This commit is contained in:
parent
ac8853dfd3
commit
87f8fb0750
43
config/config.go
Normal file
43
config/config.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfigContainer interface {
|
||||||
|
Set(key, val string) error
|
||||||
|
String(key string) string
|
||||||
|
Int(key string) (int, error)
|
||||||
|
Int64(key string) (int64, error)
|
||||||
|
Bool(key string) (bool, error)
|
||||||
|
Float(key string) (float64, error)
|
||||||
|
DIY(key string) (interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config interface {
|
||||||
|
Parse(key string) (ConfigContainer, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var adapters = make(map[string]Config)
|
||||||
|
|
||||||
|
// Register makes a config adapter available by the adapter name.
|
||||||
|
// If Register is called twice with the same name or if driver is nil,
|
||||||
|
// it panics.
|
||||||
|
func Register(name string, adapter Config) {
|
||||||
|
if adapter == nil {
|
||||||
|
panic("config: Register adapter is nil")
|
||||||
|
}
|
||||||
|
if _, dup := adapters[name]; dup {
|
||||||
|
panic("config: Register called twice for adapter " + name)
|
||||||
|
}
|
||||||
|
adapters[name] = adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
// config need to be correct JSON as string: {"interval":360}
|
||||||
|
func NewConfig(adapterName, fileaname string) (ConfigContainer, error) {
|
||||||
|
adapter, ok := adapters[adapterName]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("config: unknown adaptername %q (forgotten import?)", adapterName)
|
||||||
|
}
|
||||||
|
return adapter.Parse(fileaname)
|
||||||
|
}
|
134
config/ini.go
Normal file
134
config/ini.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
bComment = []byte{'#'}
|
||||||
|
bEmpty = []byte{}
|
||||||
|
bEqual = []byte{'='}
|
||||||
|
bDQuote = []byte{'"'}
|
||||||
|
)
|
||||||
|
|
||||||
|
type IniConfig struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseFile creates a new Config and parses the file configuration from the
|
||||||
|
// named file.
|
||||||
|
func (ini *IniConfig) Parse(name string) (ConfigContainer, error) {
|
||||||
|
file, err := os.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := &IniConfigContainer{
|
||||||
|
file.Name(),
|
||||||
|
make(map[int][]string),
|
||||||
|
make(map[string]string),
|
||||||
|
make(map[string]int64),
|
||||||
|
sync.RWMutex{},
|
||||||
|
}
|
||||||
|
cfg.Lock()
|
||||||
|
defer cfg.Unlock()
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
var comment bytes.Buffer
|
||||||
|
buf := bufio.NewReader(file)
|
||||||
|
|
||||||
|
for nComment, off := 0, int64(1); ; {
|
||||||
|
line, _, err := buf.ReadLine()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if bytes.Equal(line, bEmpty) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
off += int64(len(line))
|
||||||
|
|
||||||
|
if bytes.HasPrefix(line, bComment) {
|
||||||
|
line = bytes.TrimLeft(line, "#")
|
||||||
|
line = bytes.TrimLeftFunc(line, unicode.IsSpace)
|
||||||
|
comment.Write(line)
|
||||||
|
comment.WriteByte('\n')
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if comment.Len() != 0 {
|
||||||
|
cfg.comment[nComment] = []string{comment.String()}
|
||||||
|
comment.Reset()
|
||||||
|
nComment++
|
||||||
|
}
|
||||||
|
|
||||||
|
val := bytes.SplitN(line, bEqual, 2)
|
||||||
|
if bytes.HasPrefix([]byte(strings.TrimSpace(string(val[1]))), bDQuote) {
|
||||||
|
val[1] = bytes.Trim([]byte(strings.TrimSpace(string(val[1]))), `"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := strings.TrimSpace(string(val[0]))
|
||||||
|
cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key)
|
||||||
|
cfg.data[key] = strings.TrimSpace(string(val[1]))
|
||||||
|
cfg.offset[key] = off
|
||||||
|
}
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Config represents the configuration.
|
||||||
|
type IniConfigContainer struct {
|
||||||
|
filename string
|
||||||
|
comment map[int][]string // id: []{comment, key...}; id 1 is for main comment.
|
||||||
|
data map[string]string // key: value
|
||||||
|
offset map[string]int64 // key: offset; for editing.
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool returns the boolean value for a given key.
|
||||||
|
func (c *IniConfigContainer) Bool(key string) (bool, error) {
|
||||||
|
return strconv.ParseBool(c.data[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int returns the integer value for a given key.
|
||||||
|
func (c *IniConfigContainer) Int(key string) (int, error) {
|
||||||
|
return strconv.Atoi(c.data[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *IniConfigContainer) Int64(key string) (int64, error) {
|
||||||
|
return strconv.ParseInt(c.data[key], 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float returns the float value for a given key.
|
||||||
|
func (c *IniConfigContainer) Float(key string) (float64, error) {
|
||||||
|
return strconv.ParseFloat(c.data[key], 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string value for a given key.
|
||||||
|
func (c *IniConfigContainer) String(key string) string {
|
||||||
|
return c.data[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteValue writes a new value for key.
|
||||||
|
func (c *IniConfigContainer) Set(key, value string) error {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
c.data[key] = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||||
|
if v, ok := c.data[key]; ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return v, errors.New("key not find")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Register("ini", &IniConfig{})
|
||||||
|
}
|
66
config/ini_test.go
Normal file
66
config/ini_test.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var inicontext = `
|
||||||
|
appname = beeapi
|
||||||
|
httpport = 8080
|
||||||
|
mysqlport = 3600
|
||||||
|
PI = 3.1415976
|
||||||
|
runmode = "dev"
|
||||||
|
autorender = false
|
||||||
|
copyrequestbody = true
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestIni(t *testing.T) {
|
||||||
|
f, err := os.Create("testini.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(inicontext)
|
||||||
|
if err != nil {
|
||||||
|
f.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
defer os.Remove("testini.conf")
|
||||||
|
iniconf, err := NewConfig("ini", "testini.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if iniconf.String("appname") != "beeapi" {
|
||||||
|
t.Fatal("appname not equal to beeapi")
|
||||||
|
}
|
||||||
|
if port, err := iniconf.Int("httpport"); err != nil || port != 8080 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if port, err := iniconf.Int64("mysqlport"); err != nil || port != 3600 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if pi, err := iniconf.Float("PI"); err != nil || pi != 3.1415976 {
|
||||||
|
t.Error(pi)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if iniconf.String("runmode") != "dev" {
|
||||||
|
t.Fatal("runmode not equal to dev")
|
||||||
|
}
|
||||||
|
if v, err := iniconf.Bool("autorender"); err != nil || v != false {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := iniconf.Bool("copyrequestbody"); err != nil || v != true {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = iniconf.Set("name", "astaxie"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if iniconf.String("name") != "astaxie" {
|
||||||
|
t.Fatal("get name error")
|
||||||
|
}
|
||||||
|
}
|
90
config/json.go
Normal file
90
config/json.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JsonConfig struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
x := &JsonConfigContainer{
|
||||||
|
data: make(map[string]interface{}),
|
||||||
|
}
|
||||||
|
content, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(content, &x.data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type JsonConfigContainer struct {
|
||||||
|
data map[string]interface{}
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonConfigContainer) Bool(key string) (bool, error) {
|
||||||
|
if v, ok := c.data[key].(bool); ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return false, errors.New("not bool value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonConfigContainer) Int(key string) (int, error) {
|
||||||
|
if v, ok := c.data[key].(float64); ok {
|
||||||
|
return int(v), nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("not int value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonConfigContainer) Int64(key string) (int64, error) {
|
||||||
|
if v, ok := c.data[key].(float64); ok {
|
||||||
|
return int64(v), nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("not bool value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonConfigContainer) Float(key string) (float64, error) {
|
||||||
|
if v, ok := c.data[key].(float64); ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return 0.0, errors.New("not float64 value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonConfigContainer) String(key string) string {
|
||||||
|
if v, ok := c.data[key].(string); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonConfigContainer) Set(key, val string) error {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
c.data[key] = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||||
|
if v, ok := c.data[key]; ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("not exist key")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Register("json", &JsonConfig{})
|
||||||
|
}
|
66
config/json_test.go
Normal file
66
config/json_test.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var jsoncontext = `{
|
||||||
|
"appname": "beeapi",
|
||||||
|
"httpport": 8080,
|
||||||
|
"mysqlport": 3600,
|
||||||
|
"PI": 3.1415976,
|
||||||
|
"runmode": "dev",
|
||||||
|
"autorender": false,
|
||||||
|
"copyrequestbody": true
|
||||||
|
}`
|
||||||
|
|
||||||
|
func TestJson(t *testing.T) {
|
||||||
|
f, err := os.Create("testjson.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(jsoncontext)
|
||||||
|
if err != nil {
|
||||||
|
f.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
defer os.Remove("testjson.conf")
|
||||||
|
jsonconf, err := NewConfig("json", "testjson.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if jsonconf.String("appname") != "beeapi" {
|
||||||
|
t.Fatal("appname not equal to beeapi")
|
||||||
|
}
|
||||||
|
if port, err := jsonconf.Int("httpport"); err != nil || port != 8080 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if port, err := jsonconf.Int64("mysqlport"); err != nil || port != 3600 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if pi, err := jsonconf.Float("PI"); err != nil || pi != 3.1415976 {
|
||||||
|
t.Error(pi)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if jsonconf.String("runmode") != "dev" {
|
||||||
|
t.Fatal("runmode not equal to dev")
|
||||||
|
}
|
||||||
|
if v, err := jsonconf.Bool("autorender"); err != nil || v != false {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := jsonconf.Bool("copyrequestbody"); err != nil || v != true {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = jsonconf.Set("name", "astaxie"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if jsonconf.String("name") != "astaxie" {
|
||||||
|
t.Fatal("get name error")
|
||||||
|
}
|
||||||
|
}
|
82
config/xml.go
Normal file
82
config/xml.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//xml parse should incluce in <config></config> tags
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/clbanning/x2j"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type XMLConfig struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xmls *XMLConfig) Parse(filename string) (ConfigContainer, error) {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
x := &XMLConfigContainer{
|
||||||
|
data: make(map[string]interface{}),
|
||||||
|
}
|
||||||
|
content, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
d, err := x2j.DocToMap(string(content))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
x.data = d["config"].(map[string]interface{})
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type XMLConfigContainer struct {
|
||||||
|
data map[string]interface{}
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XMLConfigContainer) Bool(key string) (bool, error) {
|
||||||
|
return strconv.ParseBool(c.data[key].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XMLConfigContainer) Int(key string) (int, error) {
|
||||||
|
return strconv.Atoi(c.data[key].(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XMLConfigContainer) Int64(key string) (int64, error) {
|
||||||
|
return strconv.ParseInt(c.data[key].(string), 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XMLConfigContainer) Float(key string) (float64, error) {
|
||||||
|
return strconv.ParseFloat(c.data[key].(string), 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XMLConfigContainer) String(key string) string {
|
||||||
|
if v, ok := c.data[key].(string); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XMLConfigContainer) Set(key, val string) error {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
c.data[key] = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XMLConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||||
|
if v, ok := c.data[key]; ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("not exist key")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Register("xml", &XMLConfig{})
|
||||||
|
}
|
69
config/xml_test.go
Normal file
69
config/xml_test.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
//xml parse should incluce in <config></config> tags
|
||||||
|
var xmlcontext = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<config>
|
||||||
|
<appname>beeapi</appname>
|
||||||
|
<httpport>8080</httpport>
|
||||||
|
<mysqlport>3600</mysqlport>
|
||||||
|
<PI>3.1415976</PI>
|
||||||
|
<runmode>dev</runmode>
|
||||||
|
<autorender>false</autorender>
|
||||||
|
<copyrequestbody>true</copyrequestbody>
|
||||||
|
</config>
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestXML(t *testing.T) {
|
||||||
|
f, err := os.Create("testxml.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(xmlcontext)
|
||||||
|
if err != nil {
|
||||||
|
f.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
defer os.Remove("testxml.conf")
|
||||||
|
xmlconf, err := NewConfig("xml", "testxml.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if xmlconf.String("appname") != "beeapi" {
|
||||||
|
t.Fatal("appname not equal to beeapi")
|
||||||
|
}
|
||||||
|
if port, err := xmlconf.Int("httpport"); err != nil || port != 8080 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if port, err := xmlconf.Int64("mysqlport"); err != nil || port != 3600 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if pi, err := xmlconf.Float("PI"); err != nil || pi != 3.1415976 {
|
||||||
|
t.Error(pi)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if xmlconf.String("runmode") != "dev" {
|
||||||
|
t.Fatal("runmode not equal to dev")
|
||||||
|
}
|
||||||
|
if v, err := xmlconf.Bool("autorender"); err != nil || v != false {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := xmlconf.Bool("copyrequestbody"); err != nil || v != true {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = xmlconf.Set("name", "astaxie"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if xmlconf.String("name") != "astaxie" {
|
||||||
|
t.Fatal("get name error")
|
||||||
|
}
|
||||||
|
}
|
126
config/yaml.go
Normal file
126
config/yaml.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"github.com/wendal/goyaml2"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type YAMLConfig struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (yaml *YAMLConfig) Parse(filename string) (ConfigContainer, error) {
|
||||||
|
y := &YAMLConfigContainer{
|
||||||
|
data: make(map[string]interface{}),
|
||||||
|
}
|
||||||
|
cnf, err := ReadYmlReader(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
y.data = cnf
|
||||||
|
return y, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从Reader读取YAML
|
||||||
|
func ReadYmlReader(path string) (cnf map[string]interface{}, err error) {
|
||||||
|
err = nil
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
err = nil
|
||||||
|
buf, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil || len(buf) < 3 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(buf[0:1]) == "{" {
|
||||||
|
log.Println("Look lile a Json, try it")
|
||||||
|
err = json.Unmarshal(buf, &cnf)
|
||||||
|
if err == nil {
|
||||||
|
log.Println("It is Json Map")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_map, _err := goyaml2.Read(bytes.NewBuffer(buf))
|
||||||
|
if _err != nil {
|
||||||
|
log.Println("Goyaml2 ERR>", string(buf), _err)
|
||||||
|
//err = goyaml.Unmarshal(buf, &cnf)
|
||||||
|
err = _err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _map == nil {
|
||||||
|
log.Println("Goyaml2 output nil? Pls report bug\n" + string(buf))
|
||||||
|
}
|
||||||
|
cnf, ok := _map.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
log.Println("Not a Map? >> ", string(buf), _map)
|
||||||
|
cnf = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type YAMLConfigContainer struct {
|
||||||
|
data map[string]interface{}
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfigContainer) Bool(key string) (bool, error) {
|
||||||
|
if v, ok := c.data[key].(bool); ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return false, errors.New("not bool value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfigContainer) Int(key string) (int, error) {
|
||||||
|
if v, ok := c.data[key].(int); ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("not int value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfigContainer) Int64(key string) (int64, error) {
|
||||||
|
if v, ok := c.data[key].(int64); ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("not bool value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfigContainer) Float(key string) (float64, error) {
|
||||||
|
if v, ok := c.data[key].(float64); ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return 0.0, errors.New("not float64 value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfigContainer) String(key string) string {
|
||||||
|
if v, ok := c.data[key].(string); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfigContainer) Set(key, val string) error {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
c.data[key] = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *YAMLConfigContainer) DIY(key string) (v interface{}, err error) {
|
||||||
|
if v, ok := c.data[key]; ok {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("not exist key")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Register("yaml", &YAMLConfig{})
|
||||||
|
}
|
66
config/yaml_tast.go
Normal file
66
config/yaml_tast.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var yamlcontext = `
|
||||||
|
"appname": "beeapi",
|
||||||
|
"httpport": 8080,
|
||||||
|
"mysqlport": 3600,
|
||||||
|
"PI": 3.1415976,
|
||||||
|
"runmode": "dev",
|
||||||
|
"autorender": false,
|
||||||
|
"copyrequestbody": true
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestYaml(t *testing.T) {
|
||||||
|
f, err := os.Create("testyaml.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = f.WriteString(yamlcontext)
|
||||||
|
if err != nil {
|
||||||
|
f.Close()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
defer os.Remove("testyaml.conf")
|
||||||
|
yamlconf, err := NewConfig("yaml", "testyaml.conf")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if yamlconf.String("appname") != "beeapi" {
|
||||||
|
t.Fatal("appname not equal to beeapi")
|
||||||
|
}
|
||||||
|
if port, err := yamlconf.Int("httpport"); err != nil || port != 8080 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if port, err := yamlconf.Int64("mysqlport"); err != nil || port != 3600 {
|
||||||
|
t.Error(port)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if pi, err := yamlconf.Float("PI"); err != nil || pi != 3.1415976 {
|
||||||
|
t.Error(pi)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if yamlconf.String("runmode") != "dev" {
|
||||||
|
t.Fatal("runmode not equal to dev")
|
||||||
|
}
|
||||||
|
if v, err := yamlconf.Bool("autorender"); err != nil || v != false {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if v, err := yamlconf.Bool("copyrequestbody"); err != nil || v != true {
|
||||||
|
t.Error(v)
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = yamlconf.Set("name", "astaxie"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if yamlconf.String("name") != "astaxie" {
|
||||||
|
t.Fatal("get name error")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user