diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index 9125c2383..6e3131d29 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -11,11 +11,10 @@ import ( "fmt" "errors" "database/sql" - "gitee.com/johng/gf/g/os/gcache" + "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g/util/grand" _ "github.com/lib/pq" _ "github.com/go-sql-driver/mysql" - "gitee.com/johng/gf/g/util/gconv" ) const ( @@ -96,32 +95,6 @@ type Map map[string]interface{} // 关联数组列表(索引从0开始的数组),绑定多条记录 type List []Map -// 获得默认/指定分组名称的数据库操作对象单例 -func Instance (groupName...string) (*Db, error) { - name := config.d - if len(groupName) > 0 { - name = groupName[0] - } - return instance(name) -} - -// 根据配置项获取一个数据库操作对象单例 -func instance (groupName string) (*Db, error) { - instanceName := "gdb_instance_" + groupName - result := gcache.Get(instanceName) - if result == nil { - db, err := New(groupName) - if err == nil { - gcache.Set(instanceName, db, 0) - return db, nil - } else { - return nil, err - } - } else { - return result.(*Db), nil - } -} - // 使用默认/指定分组配置进行连接,数据库集群配置项:default func New(groupName...string) (*Db, error) { name := config.d @@ -161,11 +134,6 @@ func New(groupName...string) (*Db, error) { } } -// 根据单点数据库配置获得一个数据库草最对象 -func NewByNode(node ConfigNode) (*Db, error) { - return newDb (&node, nil) -} - // 按照负载均衡算法(优先级配置)从数据库集群中选择一个配置节点出来使用 func getConfigNodeByPriority (cg *ConfigGroup) *ConfigNode { if len(*cg) < 2 { @@ -210,10 +178,7 @@ func newDb (masterNode *ConfigNode, slaveNode *ConfigNode) (*Db, error) { return nil, err } } - //link.setLink(link) - //link.setMaster(master) - //link.setSlave(slave) - //link.setQuoteChar(link.getQuoteCharLeft(), link.getQuoteCharRight()) + return &Db { link : link, master : master, diff --git a/g/database/gdb/gdb_config.go b/g/database/gdb/gdb_config.go index b5f11933f..a19cb1a23 100644 --- a/g/database/gdb/gdb_config.go +++ b/g/database/gdb/gdb_config.go @@ -37,7 +37,7 @@ type ConfigNode struct { Name string // 数据库名称 Type string // 数据库类型:mysql, sqlite, mssql, pgsql, oracle(目前仅支持mysql) Role string // (可选,默认为master)数据库的角色,用于主从操作分离,至少需要有一个master,参数值:master, slave - Charset string // (可选,默认为 utf-8)编码,默认为 utf-8 + Charset string // (可选,默认为 utf8)编码,默认为 utf8 Priority int // (可选)用于负载均衡的权重计算,当集群中只有一个节点时,权重没有任何意义 Linkinfo string // (可选)自定义链接信息,当该字段被设置值时,以上链接字段(Host,Port,User,Pass,Name)将失效(该字段是一个扩展功能) } @@ -55,7 +55,7 @@ var DatabaseConfiguration = Config { Name : "test", Type : "mysql", Role : "master", - Charset : "utf-8", + Charset : "utf8", Priority : 100, }, { @@ -66,7 +66,7 @@ var DatabaseConfiguration = Config { Name : "test", Type : "mysql", Role : "slave", - Charset : "utf-8", + Charset : "utf8", Priority : 100, }, }, @@ -100,45 +100,6 @@ func AddConfigNode (group string, node ConfigNode) { config.Unlock() } -// 添加一台数据库服务器配置,通过解析规范的字符串配置实现 -// 配置格式:账号@地址:端口,密码,数据库名称,数据库类型[,集群角色(master|slave),字符编码,负载均衡优先级,自定义链接] -//func AddConfigNodeByString (group string, nodestr string) { -// reg, _ := regexp.Compile(`(.+)@(.+):([^,]+),([^,]+),([^,]+),([^,]+)`) -// match := reg.FindStringSubmatch(nodestr) -// if match != nil { -// node := ConfigNode{ -// User : strings.TrimSpace(match[1]), -// Host : strings.TrimSpace(match[2]), -// Port : strings.TrimSpace(match[3]), -// Pass : strings.TrimSpace(match[4]), -// Name : strings.TrimSpace(match[5]), -// Type : strings.TrimSpace(match[6]), -// } -// if len(match[0]) + 1 < len(nodestr) { -// extra := strings.Split(nodestr[len(match[0]) + 1:], ",") -// if len(extra) > 0 { -// node.Role = strings.TrimSpace(extra[0]) -// } -// if len(extra) > 1 { -// node.Charset = strings.TrimSpace(extra[1]) -// } -// if len(extra) > 2 { -// node.Priority, _ = strconv.Atoi(strings.TrimSpace(extra[2])) -// } -// if len(extra) > 3 { -// index := len(extra[0]) + len(extra[1]) + len(extra[2]) + 3 -// node.Linkinfo = strings.TrimSpace(nodestr[len(match[0]) + 1 + index:]) -// } -// } -// AddConfigNode(group, node) -// } -//} - -// 添加默认链接的一台数据库服务器配置,通过解析规范的字符串配置实现 -//func AddDefaultConfigNodeByString (nodestr string) { -// AddConfigNodeByString(gDEFAULT_CONFIG_GROUP_NAME, nodestr) -//} - // 添加默认链接的一台数据库服务器配置 func AddDefaultConfigNode (node ConfigNode) { AddConfigNode(gDEFAULT_CONFIG_GROUP_NAME, node) diff --git a/g/database/gredis/gredis.go b/g/database/gredis/gredis.go index 606891a26..b6eebeb8e 100644 --- a/g/database/gredis/gredis.go +++ b/g/database/gredis/gredis.go @@ -11,6 +11,8 @@ package gredis import ( "time" "github.com/gomodule/redigo/redis" + "gitee.com/johng/gf/g/container/gmap" + "gitee.com/johng/gf/g/util/gconv" ) const ( @@ -22,9 +24,8 @@ const ( // Redis客户端 type Redis struct { - address string - db interface{} - pool *redis.Pool + conn redis.Conn + pool *redis.Pool } // Redis链接池统计信息 @@ -32,27 +33,45 @@ type PoolStats struct { redis.PoolStats } +// 连接池map +var pools = gmap.NewStringInterfaceMap() + // 创建redis操作对象 // address参数格式 host:port func New(address string, db ... interface{}) *Redis { r := &Redis{} - r.address = address + dialDb := 0 if len(db) > 0 { - r.db = db[0] + dialDb = gconv.Int(db[0]) } - r.pool = &redis.Pool { - MaxIdle : gDEFAULT_POOL_MAX_IDLE, - MaxActive : gDEFAULT_POOL_MAX_ACTIVE, - IdleTimeout : gDEFAULT_POOL_IDLE_TIMEOUT, - MaxConnLifetime : gDEFAULT_POOL_MAX_LIFE_TIME, - Dial : r.dialFunc(), + poolKey := address + "," + gconv.String(dialDb) + if v := pools.Get(poolKey); v == nil { + pool := &redis.Pool { + MaxIdle : gDEFAULT_POOL_MAX_IDLE, + MaxActive : gDEFAULT_POOL_MAX_ACTIVE, + IdleTimeout : gDEFAULT_POOL_IDLE_TIMEOUT, + MaxConnLifetime : gDEFAULT_POOL_MAX_LIFE_TIME, + Dial : func() (redis.Conn, error) { + c, err := redis.Dial("tcp", address) + if err != nil { + return nil, err + } + c.Do("SELECT", dialDb) + return c, nil + }, + } + pools.Set(poolKey, pool) + r.pool = pool + } else { + r.pool = v.(*redis.Pool) } + r.conn = r.pool.Get() return r } // 关闭链接 func (r *Redis) Close() error { - return r.pool.Close() + return r.conn.Close() } // 设置属性 - MaxIdle @@ -82,26 +101,11 @@ func (r *Redis) Stats() *PoolStats { // 执行命令 - Do func (r *Redis) Do(command string, args ...interface{}) (interface{}, error) { - c := r.pool.Get() - defer c.Close() - return c.Do(command, args...) + return r.conn.Do(command, args...) } // 执行命令 - Send func (r *Redis) Send(command string, args ...interface{}) error { - c := r.pool.Get() - defer c.Close() - return c.Send(command, args...) + return r.conn.Send(command, args...) } -// 构造链接redis方法 -func (r *Redis) dialFunc() func()(redis.Conn, error) { - return func() (redis.Conn, error) { - c, err := redis.Dial("tcp", r.address) - if err != nil { - return nil, err - } - c.Do("SELECT", r.db) - return c, nil - } -} \ No newline at end of file diff --git a/g/frame/gins/gins.go b/g/frame/gins/gins.go index 67706c5b9..ca73fb28c 100644 --- a/g/frame/gins/gins.go +++ b/g/frame/gins/gins.go @@ -9,25 +9,17 @@ package gins import ( - "strconv" - "strings" "gitee.com/johng/gf/g/os/gcfg" "gitee.com/johng/gf/g/os/gcmd" "gitee.com/johng/gf/g/os/genv" "gitee.com/johng/gf/g/os/gview" "gitee.com/johng/gf/g/os/gfile" - "gitee.com/johng/gf/g/util/gconv" - "gitee.com/johng/gf/g/os/gfsnotify" - "gitee.com/johng/gf/g/database/gdb" "gitee.com/johng/gf/g/container/gmap" - "gitee.com/johng/gf/g/database/gredis" ) const ( gFRAME_CORE_COMPONENT_NAME_VIEW = "gf.core.component.view" gFRAME_CORE_COMPONENT_NAME_CONFIG = "gf.core.component.config" - gFRAME_CORE_COMPONENT_NAME_DATABASE = "gf.core.component.database" - gFRAME_CORE_COMPONENT_NAME_REDIS = "gf.core.component.redis" ) // 单例对象存储器 @@ -43,35 +35,6 @@ func Set(k string, v interface{}) { instances.Set(k, v) } -// 自定义框架核心组件:View -func SetView(v *gview.View) { - instances.Set(gFRAME_CORE_COMPONENT_NAME_VIEW, v) -} - -// 自定义框架核心组件:Config -func SetConfig(v *gcfg.Config) { - instances.Set(gFRAME_CORE_COMPONENT_NAME_CONFIG, v) -} - -// 自定义框架核心组件:Database -func SetDatabase(v *gdb.Db, name...string) { - dbCacheKey := gFRAME_CORE_COMPONENT_NAME_DATABASE - if len(name) > 0 { - dbCacheKey += name[0] - } - instances.Set(dbCacheKey, v) -} - -// 自定义框架核心组件:Redis -func SetRedis(v *gredis.Redis, name...string) { - dbCacheKey := gFRAME_CORE_COMPONENT_NAME_REDIS - if len(name) > 0 { - dbCacheKey += name[0] - } - instances.Set(dbCacheKey, v) -} - - // 核心对象:View func View() *gview.View { result := Get(gFRAME_CORE_COMPONENT_NAME_VIEW) @@ -112,106 +75,3 @@ func Config() *gcfg.Config { } return nil } - -// 核心对象:Database -func Database(name...string) *gdb.Db { - dbCacheKey := gFRAME_CORE_COMPONENT_NAME_DATABASE - if len(name) > 0 { - dbCacheKey += name[0] - } - result := Get(dbCacheKey) - if result != nil { - return result.(*gdb.Db) - } else { - config := Config() - if config == nil { - return nil - } - if m := config.GetMap("database"); m != nil { - for group, v := range m { - if list, ok := v.([]interface{}); ok { - for _, nodev := range list { - node := gdb.ConfigNode{} - nodem := nodev.(map[string]interface{}) - if value, ok := nodem["host"]; ok { - node.Host = value.(string) - } - if value, ok := nodem["port"]; ok { - node.Port = value.(string) - } - if value, ok := nodem["user"]; ok { - node.User = value.(string) - } - if value, ok := nodem["pass"]; ok { - node.Pass = value.(string) - } - if value, ok := nodem["name"]; ok { - node.Name = value.(string) - } - if value, ok := nodem["type"]; ok { - node.Type = value.(string) - } - if value, ok := nodem["role"]; ok { - node.Role = value.(string) - } - if value, ok := nodem["charset"]; ok { - node.Charset = value.(string) - } - if value, ok := nodem["priority"]; ok { - node.Priority, _ = strconv.Atoi(value.(string)) - } - gdb.AddConfigNode(group, node) - } - } - } - // 这里不能用Instance方法,否则无法自动检测更新 - if db, err := gdb.New(name...); err == nil { - Set(dbCacheKey, db) - // 监控配置变化,一单有变化马上清空单例对象,下一次重新获取 - // 无法对特定操作进行判断,不同编辑器的行为引起的操作回调提醒不一样 - gfsnotify.Add(config.GetFilePath(), func(event *gfsnotify.Event) { - Set(dbCacheKey, nil) - }) - return db - } else { - return nil - } - } - } - return nil -} - -// 核心对象:Redis -func Redis(name...string) *gredis.Redis { - group := "default" - redisCacheKey := gFRAME_CORE_COMPONENT_NAME_REDIS - if len(name) > 0 { - group = name[0] - redisCacheKey += name[0] - } - result := Get(redisCacheKey) - if result != nil { - return result.(*gredis.Redis) - } else { - config := Config() - if config == nil { - return nil - } - if m := config.GetMap("redis"); m != nil { - if v, ok := m[group]; ok { - array := strings.Split(gconv.String(v), ",") - if len(array) > 1 { - redis := gredis.New(array[0], array[1]) - Set(redisCacheKey, redis) - // 监控配置变化,一单有变化马上清空单例对象,下一次重新获取 - // 无法对特定操作进行判断,不同编辑器的行为引起的操作回调提醒不一样 - gfsnotify.Add(config.GetFilePath(), func(event *gfsnotify.Event) { - Set(redisCacheKey, nil) - }) - return redis - } - } - } - } - return nil -} \ No newline at end of file diff --git a/g/g.go b/g/g.go index bb86eea25..e9bad31f2 100644 --- a/g/g.go +++ b/g/g.go @@ -3,11 +3,19 @@ // This Source Code Form is subject to the terms of the MIT License. // If a copy of the MIT was not distributed with this file, // You can obtain one at https://gitee.com/johng/gf. +// 常用数据类型以及对象封装 package g import ( - "html/template" + "strings" + "strconv" + "gitee.com/johng/gf/g/os/gview" + "gitee.com/johng/gf/g/os/gcfg" + "gitee.com/johng/gf/g/util/gconv" + "gitee.com/johng/gf/g/frame/gins" + "gitee.com/johng/gf/g/database/gdb" + "gitee.com/johng/gf/g/database/gredis" ) // 常用map数据结构 @@ -16,8 +24,93 @@ type Map map[string]interface{} // 常用list数据结构 type List []Map - -// 输出到模板页面时保留HTML标签原意,不做自动escape处理 -func HTML(content string) template.HTML { - return template.HTML(content) +// 核心对象:View +func View() *gview.View { + return gins.View() } + +// Config配置管理对象 +// 配置文件目录查找依次为:启动参数cfgpath、当前程序运行目录 +func Config() *gcfg.Config { + return gins.Config() +} + + +// 数据库操作对象,使用了连接池 +func Database(name...string) *gdb.Db { + config := gins.Config() + if config == nil { + return nil + } + if m := config.GetMap("database"); m != nil { + c := gdb.Config{} + for group, v := range m { + cg := gdb.ConfigGroup{} + if list, ok := v.([]interface{}); ok { + for _, nodev := range list { + node := gdb.ConfigNode{} + nodem := nodev.(map[string]interface{}) + if value, ok := nodem["host"]; ok { + node.Host = gconv.String(value) + } + if value, ok := nodem["port"]; ok { + node.Port = gconv.String(value) + } + if value, ok := nodem["user"]; ok { + node.User = gconv.String(value) + } + if value, ok := nodem["pass"]; ok { + node.Pass = gconv.String(value) + } + if value, ok := nodem["name"]; ok { + node.Name = gconv.String(value) + } + if value, ok := nodem["type"]; ok { + node.Type = gconv.String(value) + } + if value, ok := nodem["role"]; ok { + node.Role = gconv.String(value) + } + if value, ok := nodem["charset"]; ok { + node.Charset = gconv.String(value) + } + if value, ok := nodem["priority"]; ok { + node.Priority, _ = strconv.Atoi(gconv.String(value)) + } + cg = append(cg, node) + } + } + c[group] = cg + } + gdb.SetConfig(c) + + if db, err := gdb.New(name...); err == nil { + return db + } else { + return nil + } + } + + return nil +} + +// Redis操作对象,使用了连接池 +func Redis(name...string) *gredis.Redis { + group := "default" + if len(name) > 0 { + group = name[0] + } + config := gins.Config() + if config == nil { + return nil + } + if m := config.GetMap("redis"); m != nil { + if v, ok := m[group]; ok { + array := strings.Split(gconv.String(v), ",") + if len(array) > 1 { + return gredis.New(array[0], array[1]) + } + } + } + return nil +} \ No newline at end of file diff --git a/geg/database/mysql/mysql.go b/geg/database/mysql/mysql.go index 3b49c1775..796839c67 100644 --- a/geg/database/mysql/mysql.go +++ b/geg/database/mysql/mysql.go @@ -5,6 +5,7 @@ import ( "time" "gitee.com/johng/gf/g/database/gdb" "gitee.com/johng/gf/g" + "gitee.com/johng/gf/g/frame/gins" ) // 本文件用于gf框架的mysql数据库操作示例,不作为单元测试使用 @@ -13,17 +14,20 @@ var db *gdb.Db // 初始化配置及创建数据库 func init () { - gdb.AddDefaultConfigNode(gdb.ConfigNode { - Host : "127.0.0.1", - Port : "3306", - User : "root", - Pass : "8692651", - Name : "test", - Type : "mysql", - Role : "master", - Charset : "utf8", - }) - db, _ = gdb.Instance() + //gdb.AddDefaultConfigNode(gdb.ConfigNode { + // Host : "127.0.0.1", + // Port : "3306", + // User : "root", + // Pass : "8692651", + // Name : "test", + // Type : "mysql", + // Role : "master", + // Charset : "utf8", + //}) + //db, _ = gdb.New() + + gins.Config().SetPath("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame") + db = g.Database() //gdb.SetConfig(gdb.ConfigNode { // Host : "127.0.0.1", @@ -444,9 +448,9 @@ func keepPing() { // 数据库单例测试,在mysql中使用 show full processlist 查看链接信息 func instance() { fmt.Println("instance:") - db1, _ := gdb.Instance() - db2, _ := gdb.Instance() - db3, _ := gdb.Instance() + db1, _ := gdb.New() + db2, _ := gdb.New() + db3, _ := gdb.New() for { fmt.Println("ping...") db1.PingMaster() diff --git a/geg/database/redis/gredis.go b/geg/database/redis/gredis.go index 6c37ac69d..d08c0119f 100644 --- a/geg/database/redis/gredis.go +++ b/geg/database/redis/gredis.go @@ -8,6 +8,7 @@ import ( func main() { redis := gredis.New("127.0.0.1:6379", 1) + defer redis.Close() redis.Do("SET", "k1", "v1") redis.Do("SET", "k2", "v2") v1, _ := redis.Do("GET", "k1") diff --git a/geg/database/redis/gredis_gins.go b/geg/database/redis/gredis_gins.go deleted file mode 100644 index 2bf7f2392..000000000 --- a/geg/database/redis/gredis_gins.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "time" - "gitee.com/johng/gf/g/os/gtime" - "gitee.com/johng/gf/g/frame/gins" -) - -func main() { - gins.Config().SetPath("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame") - gtime.SetInterval(2*time.Second, func() bool { - redis := gins.Redis("cache") - redis.Do("GET", "k") - return true - }) - select{} -} - diff --git a/geg/frame/config.yml b/geg/frame/config.yml index 5f48c0d83..84a2fa21c 100644 --- a/geg/frame/config.yml +++ b/geg/frame/config.yml @@ -6,20 +6,20 @@ database: - host: 127.0.0.1 port: 3306 user: root - pass: 123456 + pass: "8692651" name: test type: mysql role: master - charset: utf-8 + charset: utf8 priority: 1 - host: 127.0.0.1 port: 3306 user: root - pass: 123456 + pass: "8692651" name: test type: mysql role: master - charset: utf-8 + charset: utf8 priority: 1 # Redis数据库配置 redis: diff --git a/geg/frame/mvc/controller/demo/template2.go b/geg/frame/mvc/controller/demo/template2.go index 99aa19b32..4f6b92050 100644 --- a/geg/frame/mvc/controller/demo/template2.go +++ b/geg/frame/mvc/controller/demo/template2.go @@ -2,12 +2,12 @@ package demo import ( "gitee.com/johng/gf/g/net/ghttp" - "gitee.com/johng/gf/g/frame/gins" + "gitee.com/johng/gf/g" ) func init() { ghttp.GetServer().BindHandler("/template2", func(r *ghttp.Request){ - content, _ := gins.View().Parse("index.tpl", map[string]interface{}{ + content, _ := g.View().Parse("index.tpl", map[string]interface{}{ "id" : 123, "name" : "john", }) diff --git a/geg/other/test.go b/geg/other/test.go index 5231cdbb8..c6e2c58c7 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -2,15 +2,11 @@ package main import ( "fmt" - "strings" + "gitee.com/johng/gf/g" ) func main() { - s1 := `C:\Documents and Settings\Claymore\桌面\gf.test` - s2 := `C:\Documents and Settings\Claymore\桌面\gf.tes` + fmt.Println(g.Map{}) - - - - fmt.Println(len(s2) >= len(s1) && strings.EqualFold(s2[0 : len(s1)], s1) ) + select {} } \ No newline at end of file diff --git a/geg/util/gpage/gpage.go b/geg/util/gpage/gpage.go index ab0003f3d..a9c96fd2d 100644 --- a/geg/util/gpage/gpage.go +++ b/geg/util/gpage/gpage.go @@ -27,10 +27,10 @@ func main() { `, g.Map{ - "page1" : g.HTML(page.GetContent(1)), - "page2" : g.HTML(page.GetContent(2)), - "page3" : g.HTML(page.GetContent(3)), - "page4" : g.HTML(page.GetContent(4)), + "page1" : gview.HTML(page.GetContent(1)), + "page2" : gview.HTML(page.GetContent(2)), + "page3" : gview.HTML(page.GetContent(3)), + "page4" : gview.HTML(page.GetContent(4)), }) r.Response.Write(buffer) }) diff --git a/geg/util/gpage/gpage_ajax.go b/geg/util/gpage/gpage_ajax.go index ad587c411..91b2625a9 100644 --- a/geg/util/gpage/gpage_ajax.go +++ b/geg/util/gpage/gpage_ajax.go @@ -33,7 +33,7 @@ func main() { `, g.Map{ - "page" : g.HTML(page.GetContent(1)), + "page" : gview.HTML(page.GetContent(1)), }) r.Response.Write(buffer) }) diff --git a/geg/util/gpage/gpage_custom.go b/geg/util/gpage/gpage_custom.go index 6a70883e0..41658626b 100644 --- a/geg/util/gpage/gpage_custom.go +++ b/geg/util/gpage/gpage_custom.go @@ -38,7 +38,7 @@ func main() { `, g.Map{ - "page" : g.HTML(pageContent(page)), + "page" : gview.HTML(pageContent(page)), }) r.Response.Write(buffer) }) diff --git a/geg/util/gpage/gpage_static.go b/geg/util/gpage/gpage_static.go index 85f96038c..324c23261 100644 --- a/geg/util/gpage/gpage_static.go +++ b/geg/util/gpage/gpage_static.go @@ -27,10 +27,10 @@ func main() { `, g.Map{ - "page1" : g.HTML(page.GetContent(1)), - "page2" : g.HTML(page.GetContent(2)), - "page3" : g.HTML(page.GetContent(3)), - "page4" : g.HTML(page.GetContent(4)), + "page1" : gview.HTML(page.GetContent(1)), + "page2" : gview.HTML(page.GetContent(2)), + "page3" : gview.HTML(page.GetContent(3)), + "page4" : gview.HTML(page.GetContent(4)), }) r.Response.Write(buffer) })