完成gmvc基本开发及测试

This commit is contained in:
John 2017-12-20 12:05:36 +08:00
parent 03109055c1
commit aacb6abb9a
13 changed files with 279 additions and 170 deletions

View File

@ -20,7 +20,7 @@ import "gitee.com/johng/gf/g/xxx/xxx"
│   │   └── gset 并发安全的集合 │   │   └── gset 并发安全的集合
│   │   │   │  
│   ├── database 【数据库操作】 │   ├── database 【数据库操作】
│   │   └── gdb MySQL、PostgreSQL的操作封装 │   │   └── gdb 通用关系型数据库操作封装(目前仅支持MySQL、PostgreSQL)
│   │   │   │  
│   ├── encoding 【数据编码】 │   ├── encoding 【数据编码】
│   │   ├── gbase64 BASE64 │   │   ├── gbase64 BASE64
@ -34,10 +34,16 @@ import "gitee.com/johng/gf/g/xxx/xxx"
│   │   ├── gsha1 SHA1 │   │   ├── gsha1 SHA1
│   │   └── gurl URL │   │   └── gurl URL
│   │   │   │  
│   ├── frame 【开发框架】
│   │   ├── gconfig 通用配置管理
│   │   ├── ginstance 单例对象管理
│   │   └── gmvc MVC模式封装基类
│   │  
│   ├── net 【网络通信】 │   ├── net 【网络通信】
│   │   ├── ghttp HTTP客户端及服务端 │   │   ├── ghttp HTTP客户端及服务端
│   │   ├── gip IP操作 │   │   ├── gipv4 IP操作
│   │   ├── gscanner 端口扫描 │   │   ├── gscanner 端口扫描
│   │   ├── gsession SESSION会话管理
│   │   ├── gsmtp SMTP邮件管理 │   │   ├── gsmtp SMTP邮件管理
│   │   ├── gtcp TCP服务端 │   │   ├── gtcp TCP服务端
│   │   └── gudp UDP服务端 │   │   └── gudp UDP服务端
@ -45,12 +51,14 @@ import "gitee.com/johng/gf/g/xxx/xxx"
│   ├── os 【系统管理】 │   ├── os 【系统管理】
│   │   ├── gcache 本地缓存管理 │   │   ├── gcache 本地缓存管理
│   │   ├── gconsole 命令行控制 │   │   ├── gconsole 命令行控制
│   │   ├── genv 环境变量管理
│   │   ├── gfile 文件管理 │   │   ├── gfile 文件管理
│   │   ├── gfilepool 文件指针池 │   │   ├── gfilepool 文件指针池
│   │   ├── gfilespace 文件碎片管理 │   │   ├── gfilespace 文件碎片管理
│   │   ├── glog 日志管理 │   │   ├── glog 日志管理
│   │ ├── gmmap MMAP文件内存映射 │   │ ├── gmmap MMAP文件内存映射
│   │   └── gtime 时间管理 │   │   ├── gtime 时间管理
│   │   └── gview 视图管理(通用的模板管理对象独立于MVC模块)
│   │   │   │  
│   └── util 【常用工具】 │   └── util 【常用工具】
│   ├── gpage 分页 │   ├── gpage 分页
@ -65,3 +73,70 @@ import "gitee.com/johng/gf/g/xxx/xxx"
## 配置 ## 配置
1. 默认读取文件运行目录的config.json文件 1. 默认读取文件运行目录的config.json文件
1. 支持多配置文件管理,默认配置文件目录为当前运行目录; 1. 支持多配置文件管理,默认配置文件目录为当前运行目录;
1. config.json配置文件说明
```json
{
"viewpath" : "视图文件存放路径",
"database" : {
"数据库分组名称" : [
{
"host" : "地址",
"port" : "端口",
"user" : "账号",
"pass" : "密码",
"name" : "数据库名称",
"type" : "数据库类型(mysql|pgsql)",
"role" : "数据库角色(master|slave)",
"charset" : "字符编码",
"priority" : "数据库优先级(负载均衡处理)"
}
]
}
}
```
1. config.json示例文件
```json
{
"viewpath" : "/home/john/Workspace/Go/gitee.com/johng/gf/geg/frame/mvc/view",
"database" : {
"default" : [
{
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "123456",
"name" : "test",
"type" : "mysql",
"role" : "master",
"charset" : "utf8",
"priority" : "100"
},
{
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "123456",
"name" : "test",
"type" : "mysql",
"role" : "slave",
"charset" : "utf8",
"priority" : "100"
}
],
"ucenter" : [
{
"host" : "127.0.0.1",
"port" : "3306",
"user" : "root",
"pass" : "123456",
"name" : "ucenter",
"type" : "mysql",
"role" : "master",
"charset" : "utf8",
"priority" : "100"
}
]
}
}
```

View File

@ -27,8 +27,8 @@ type Link interface {
Exec(q string, args ...interface{}) (sql.Result, error) Exec(q string, args ...interface{}) (sql.Result, error)
Prepare(q string) (*sql.Stmt, error) Prepare(q string) (*sql.Stmt, error)
GetAll(q string, args ...interface{}) (*List, error) GetAll(q string, args ...interface{}) (List, error)
GetOne(q string, args ...interface{}) (*Map, error) GetOne(q string, args ...interface{}) (Map, error)
GetValue(q string, args ...interface{}) (interface{}, error) GetValue(q string, args ...interface{}) (interface{}, error)
PingMaster() error PingMaster() error
@ -49,15 +49,15 @@ type Link interface {
Commit() error Commit() error
Rollback() error Rollback() error
insert(table string, data *Map, option uint8) (sql.Result, error) insert(table string, data Map, option uint8) (sql.Result, error)
Insert(table string, data *Map) (sql.Result, error) Insert(table string, data Map) (sql.Result, error)
Replace(table string, data *Map) (sql.Result, error) Replace(table string, data Map) (sql.Result, error)
Save(table string, data *Map) (sql.Result, error) Save(table string, data Map) (sql.Result, error)
batchInsert(table string, list *List, batch int, option uint8) error batchInsert(table string, list List, batch int, option uint8) error
BatchInsert(table string, list *List, batch int) error BatchInsert(table string, list List, batch int) error
BatchReplace(table string, list *List, batch int) error BatchReplace(table string, list List, batch int) error
BatchSave(table string, list *List, batch int) error BatchSave(table string, list List, batch int) error
Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error)
Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error)
@ -136,7 +136,6 @@ func NewByGroup(groupName string) (Link, error) {
if len(masterList) < 1 { if len(masterList) < 1 {
return nil, errors.New("at least one master node configuration's need to make sense") return nil, errors.New("at least one master node configuration's need to make sense")
} }
fmt.Println(masterList)
masterNode := getConfigNodeByPriority(&masterList) masterNode := getConfigNodeByPriority(&masterList)
var slaveNode *ConfigNode var slaveNode *ConfigNode
if len(slaveList) > 0 { if len(slaveList) > 0 {

View File

@ -67,7 +67,7 @@ func (l *dbLink) formatError(err error, q *string, args ...interface{}) error {
// 数据库查询,获取查询结果集,以列表结构返回 // 数据库查询,获取查询结果集,以列表结构返回
func (l *dbLink) GetAll(q string, args ...interface{}) (*List, error) { func (l *dbLink) GetAll(q string, args ...interface{}) (List, error) {
// 执行sql // 执行sql
rows, err := l.Query(q, args ...) rows, err := l.Query(q, args ...)
if err != nil || rows == nil { if err != nil || rows == nil {
@ -88,7 +88,7 @@ func (l *dbLink) GetAll(q string, args ...interface{}) (*List, error) {
for rows.Next() { for rows.Next() {
err = rows.Scan(scanArgs...) err = rows.Scan(scanArgs...)
if err != nil { if err != nil {
return &list, err return list, err
} }
row := make(Map) row := make(Map)
for i, col := range values { for i, col := range values {
@ -96,16 +96,16 @@ func (l *dbLink) GetAll(q string, args ...interface{}) (*List, error) {
} }
list = append(list, row) list = append(list, row)
} }
return &list, nil return list, nil
} }
// 数据库查询,获取查询结果集,以关联数组结构返回 // 数据库查询,获取查询结果集,以关联数组结构返回
func (l *dbLink) GetOne(q string, args ...interface{}) (*Map, error) { func (l *dbLink) GetOne(q string, args ...interface{}) (Map, error) {
list, err := l.GetAll(q, args ...) list, err := l.GetAll(q, args ...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &(*list)[0], nil return list[0], nil
} }
// 数据库查询,获取查询字段值 // 数据库查询,获取查询字段值
@ -114,7 +114,7 @@ func (l *dbLink) GetValue(q string, args ...interface{}) (interface{}, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
for _, v := range *one { for _, v := range one {
return v, nil return v, nil
} }
return "", nil return "", nil
@ -194,11 +194,11 @@ func (l *dbLink) getInsertOperationByOption(option uint8) string {
// 1: replace: 如果数据存在(主键或者唯一索引),那么删除后重新写入一条 // 1: replace: 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
// 2: save: 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据 // 2: save: 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
// 3: ignore: 如果数据存在(主键或者唯一索引),那么什么也不做 // 3: ignore: 如果数据存在(主键或者唯一索引),那么什么也不做
func (l *dbLink) insert(table string, data *Map, option uint8) (sql.Result, error) { func (l *dbLink) insert(table string, data Map, option uint8) (sql.Result, error) {
var keys []string var keys []string
var values []string var values []string
var params []interface{} var params []interface{}
for k, v := range *data { for k, v := range data {
keys = append(keys, l.charl + k + l.charr) keys = append(keys, l.charl + k + l.charr)
values = append(values, "?") values = append(values, "?")
params = append(params, v) params = append(params, v)
@ -207,7 +207,7 @@ func (l *dbLink) insert(table string, data *Map, option uint8) (sql.Result, erro
updatestr := "" updatestr := ""
if option == OPTION_SAVE { if option == OPTION_SAVE {
var updates []string var updates []string
for k, _ := range *data { for k, _ := range data {
updates = append(updates, fmt.Sprintf("%s%s%s=VALUES(%s)", l.charl, k, l.charr, k)) updates = append(updates, fmt.Sprintf("%s%s%s=VALUES(%s)", l.charl, k, l.charr, k))
} }
updatestr = fmt.Sprintf(" ON DUPLICATE KEY UPDATE %s", strings.Join(updates, ",")) updatestr = fmt.Sprintf(" ON DUPLICATE KEY UPDATE %s", strings.Join(updates, ","))
@ -219,33 +219,33 @@ func (l *dbLink) insert(table string, data *Map, option uint8) (sql.Result, erro
} }
// CURD操作:单条数据写入, 仅仅执行写入操作,如果存在冲突的主键或者唯一索引,那么报错返回 // CURD操作:单条数据写入, 仅仅执行写入操作,如果存在冲突的主键或者唯一索引,那么报错返回
func (l *dbLink) Insert(table string, data *Map) (sql.Result, error) { func (l *dbLink) Insert(table string, data Map) (sql.Result, error) {
return l.link.insert(table, data, OPTION_INSERT) return l.link.insert(table, data, OPTION_INSERT)
} }
// CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条 // CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
func (l *dbLink) Replace(table string, data *Map) (sql.Result, error) { func (l *dbLink) Replace(table string, data Map) (sql.Result, error) {
return l.link.insert(table, data, OPTION_REPLACE) return l.link.insert(table, data, OPTION_REPLACE)
} }
// CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据 // CURD操作:单条数据写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
func (l *dbLink) Save(table string, data *Map) (sql.Result, error) { func (l *dbLink) Save(table string, data Map) (sql.Result, error) {
return l.link.insert(table, data, OPTION_SAVE) return l.link.insert(table, data, OPTION_SAVE)
} }
// 批量写入数据 // 批量写入数据
func (l *dbLink) batchInsert(table string, list *List, batch int, option uint8) error { func (l *dbLink) batchInsert(table string, list List, batch int, option uint8) error {
var keys []string var keys []string
var values []string var values []string
var bvalues []string var bvalues []string
var params []interface{} var params []interface{}
var size int = len(*list) var size int = len(list)
// 判断长度 // 判断长度
if size < 1 { if size < 1 {
return errors.New("empty data list") return errors.New("empty data list")
} }
// 首先获取字段名称及记录长度 // 首先获取字段名称及记录长度
for k, _ := range (*list)[0] { for k, _ := range list[0] {
keys = append(keys, k) keys = append(keys, k)
values = append(values, "?") values = append(values, "?")
} }
@ -263,7 +263,7 @@ func (l *dbLink) batchInsert(table string, list *List, batch int, option uint8)
// 构造批量写入数据格式(注意map的遍历是无序的) // 构造批量写入数据格式(注意map的遍历是无序的)
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
for _, k := range keys { for _, k := range keys {
params = append(params, (*list)[i][k]) params = append(params, list[i][k])
} }
bvalues = append(bvalues, "(" + strings.Join(values, ",") + ")") bvalues = append(bvalues, "(" + strings.Join(values, ",") + ")")
if len(bvalues) == batch { if len(bvalues) == batch {
@ -285,17 +285,17 @@ func (l *dbLink) batchInsert(table string, list *List, batch int, option uint8)
} }
// CURD操作:批量数据指定批次量写入 // CURD操作:批量数据指定批次量写入
func (l *dbLink) BatchInsert(table string, list *List, batch int) error { func (l *dbLink) BatchInsert(table string, list List, batch int) error {
return l.link.batchInsert(table, list, batch, OPTION_INSERT) return l.link.batchInsert(table, list, batch, OPTION_INSERT)
} }
// CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条 // CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么删除后重新写入一条
func (l *dbLink) BatchReplace(table string, list *List, batch int) error { func (l *dbLink) BatchReplace(table string, list List, batch int) error {
return l.link.batchInsert(table, list, batch, OPTION_REPLACE) return l.link.batchInsert(table, list, batch, OPTION_REPLACE)
} }
// CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据 // CURD操作:批量数据指定批次量写入, 如果数据存在(主键或者唯一索引),那么更新,否则写入一条新数据
func (l *dbLink) BatchSave(table string, list *List, batch int) error { func (l *dbLink) BatchSave(table string, list List, batch int) error {
return l.link.batchInsert(table, list, batch, OPTION_SAVE) return l.link.batchInsert(table, list, batch, OPTION_SAVE)
} }
@ -307,16 +307,16 @@ func (l *dbLink) Update(table string, data interface{}, condition interface{}, a
switch data.(type) { switch data.(type) {
case string: case string:
updates = data.(string) updates = data.(string)
case *Map: case Map:
var keys []string var keys []string
for k, v := range *data.(*Map) { for k, v := range data.(Map) {
keys = append(keys, fmt.Sprintf("%s%s%s=?", l.charl, k, l.charr)) keys = append(keys, fmt.Sprintf("%s%s%s=?", l.charl, k, l.charr))
params = append(params, v) params = append(params, v)
} }
updates = strings.Join(keys, ",") updates = strings.Join(keys, ",")
default: default:
return nil, errors.New("invalid data type for 'data' field, string or *Map expected") return nil, errors.New("invalid data type for 'data' field, string or Map expected")
} }
for _, v := range args { for _, v := range args {
if r, ok := v.(string); ok { if r, ok := v.(string); ok {

View File

@ -3,9 +3,6 @@ package gdb
import ( import (
"sync" "sync"
"regexp"
"strings"
"strconv"
) )
const ( const (
@ -99,42 +96,42 @@ func AddConfigNode (group string, node ConfigNode) {
// 添加一台数据库服务器配置,通过解析规范的字符串配置实现 // 添加一台数据库服务器配置,通过解析规范的字符串配置实现
// 配置格式:账号@地址:端口,密码,数据库名称,数据库类型[,集群角色(master|slave),字符编码,负载均衡优先级,自定义链接] // 配置格式:账号@地址:端口,密码,数据库名称,数据库类型[,集群角色(master|slave),字符编码,负载均衡优先级,自定义链接]
func AddConfigNodeByString (group string, nodestr string) { //func AddConfigNodeByString (group string, nodestr string) {
reg, _ := regexp.Compile(`(.+)@(.+):([^,]+),([^,]+),([^,]+),([^,]+)`) // reg, _ := regexp.Compile(`(.+)@(.+):([^,]+),([^,]+),([^,]+),([^,]+)`)
match := reg.FindStringSubmatch(nodestr) // match := reg.FindStringSubmatch(nodestr)
if match != nil { // if match != nil {
node := ConfigNode{ // node := ConfigNode{
User : strings.TrimSpace(match[1]), // User : strings.TrimSpace(match[1]),
Host : strings.TrimSpace(match[2]), // Host : strings.TrimSpace(match[2]),
Port : strings.TrimSpace(match[3]), // Port : strings.TrimSpace(match[3]),
Pass : strings.TrimSpace(match[4]), // Pass : strings.TrimSpace(match[4]),
Name : strings.TrimSpace(match[5]), // Name : strings.TrimSpace(match[5]),
Type : strings.TrimSpace(match[6]), // Type : strings.TrimSpace(match[6]),
} // }
if len(match[0]) + 1 < len(nodestr) { // if len(match[0]) + 1 < len(nodestr) {
extra := strings.Split(nodestr[len(match[0]) + 1:], ",") // extra := strings.Split(nodestr[len(match[0]) + 1:], ",")
if len(extra) > 0 { // if len(extra) > 0 {
node.Role = strings.TrimSpace(extra[0]) // node.Role = strings.TrimSpace(extra[0])
} // }
if len(extra) > 1 { // if len(extra) > 1 {
node.Charset = strings.TrimSpace(extra[1]) // node.Charset = strings.TrimSpace(extra[1])
} // }
if len(extra) > 2 { // if len(extra) > 2 {
node.Priority, _ = strconv.Atoi(strings.TrimSpace(extra[2])) // node.Priority, _ = strconv.Atoi(strings.TrimSpace(extra[2]))
} // }
if len(extra) > 3 { // if len(extra) > 3 {
index := len(extra[0]) + len(extra[1]) + len(extra[2]) + 3 // index := len(extra[0]) + len(extra[1]) + len(extra[2]) + 3
node.Linkinfo = strings.TrimSpace(nodestr[len(match[0]) + 1 + index:]) // node.Linkinfo = strings.TrimSpace(nodestr[len(match[0]) + 1 + index:])
} // }
} // }
AddConfigNode(group, node) // AddConfigNode(group, node)
} // }
} //}
// 添加默认链接的一台数据库服务器配置,通过解析规范的字符串配置实现 // 添加默认链接的一台数据库服务器配置,通过解析规范的字符串配置实现
func AddDefaultConfigNodeByString (nodestr string) { //func AddDefaultConfigNodeByString (nodestr string) {
AddConfigNodeByString(gDEFAULT_CONFIG_GROUP_NAME, nodestr) // AddConfigNodeByString(gDEFAULT_CONFIG_GROUP_NAME, nodestr)
} //}
// 添加默认链接的一台数据库服务器配置 // 添加默认链接的一台数据库服务器配置
func AddDefaultConfigNode (node ConfigNode) { func AddDefaultConfigNode (node ConfigNode) {

View File

@ -19,7 +19,7 @@ type gLinkOp struct {
start int start int
limit int limit int
data interface{} data interface{}
dataList *List dataList List
batch int batch int
} }
@ -88,7 +88,7 @@ func (op *gLinkOp) Data(data interface{}) (*gLinkOp) {
} }
// 链式操作,操作数据记录项列表 // 链式操作,操作数据记录项列表
func (op *gLinkOp) List(list *List) (*gLinkOp) { func (op *gLinkOp) List(list List) (*gLinkOp) {
op.dataList = list op.dataList = list
return op return op
} }
@ -98,7 +98,7 @@ func (op *gLinkOp) Insert() (sql.Result, error) {
if op.data == nil { if op.data == nil {
return nil, errors.New("inserting into table with empty data") return nil, errors.New("inserting into table with empty data")
} }
if d, ok := op.data.(*Map); ok { if d, ok := op.data.(Map); ok {
return op.link.Insert(op.tables, d) return op.link.Insert(op.tables, d)
} }
return nil, errors.New("inserting into table with invalid data type") return nil, errors.New("inserting into table with invalid data type")
@ -109,7 +109,7 @@ func (op *gLinkOp) Replace() (sql.Result, error) {
if op.data == nil { if op.data == nil {
return nil, errors.New("replacing into table with empty data") return nil, errors.New("replacing into table with empty data")
} }
if d, ok := op.data.(*Map); ok { if d, ok := op.data.(Map); ok {
return op.link.Insert(op.tables, d) return op.link.Insert(op.tables, d)
} }
return nil, errors.New("replacing into table with invalid data type") return nil, errors.New("replacing into table with invalid data type")
@ -120,7 +120,7 @@ func (op *gLinkOp) Save() (sql.Result, error) {
if op.data == nil { if op.data == nil {
return nil, errors.New("saving into table with empty data") return nil, errors.New("saving into table with empty data")
} }
if d, ok := op.data.(*Map); ok { if d, ok := op.data.(Map); ok {
return op.link.Insert(op.tables, d) return op.link.Insert(op.tables, d)
} }
return nil, errors.New("saving into table with invalid data type") return nil, errors.New("saving into table with invalid data type")
@ -134,7 +134,7 @@ func (op *gLinkOp) Batch(batch int) *gLinkOp {
// 链式操作, CURD - BatchInsert // 链式操作, CURD - BatchInsert
func (op *gLinkOp) BatchInsert() error { func (op *gLinkOp) BatchInsert() error {
if op.dataList == nil || len(*op.dataList) < 1 { if op.dataList == nil || len(op.dataList) < 1 {
return errors.New("batch inserting into table with empty data list") return errors.New("batch inserting into table with empty data list")
} }
batch := 10 batch := 10
@ -146,7 +146,7 @@ func (op *gLinkOp) BatchInsert() error {
// 链式操作, CURD - BatchReplace // 链式操作, CURD - BatchReplace
func (op *gLinkOp) BatchReplace() error { func (op *gLinkOp) BatchReplace() error {
if op.dataList == nil || len(*op.dataList) < 1 { if op.dataList == nil || len(op.dataList) < 1 {
return errors.New("batch replacing into table with empty data list") return errors.New("batch replacing into table with empty data list")
} }
batch := 10 batch := 10
@ -158,7 +158,7 @@ func (op *gLinkOp) BatchReplace() error {
// 链式操作, CURD - BatchSave // 链式操作, CURD - BatchSave
func (op *gLinkOp) BatchSave() error { func (op *gLinkOp) BatchSave() error {
if op.dataList == nil || len(*op.dataList) < 1 { if op.dataList == nil || len(op.dataList) < 1 {
return errors.New("batch saving into table with empty data list") return errors.New("batch saving into table with empty data list")
} }
batch := 10 batch := 10
@ -185,7 +185,7 @@ func (op *gLinkOp) Delete() (sql.Result, error) {
} }
// 链式操作select // 链式操作select
func (op *gLinkOp) Select() (*List, error) { func (op *gLinkOp) Select() (List, error) {
if op.fields == "" { if op.fields == "" {
op.fields = "*" op.fields = "*"
} }
@ -206,17 +206,17 @@ func (op *gLinkOp) Select() (*List, error) {
} }
// 链式操作,查询所有记录 // 链式操作,查询所有记录
func (op *gLinkOp) All() (*List, error) { func (op *gLinkOp) All() (List, error) {
return op.Select() return op.Select()
} }
// 链式操作,查询单条记录 // 链式操作,查询单条记录
func (op *gLinkOp) One() (*Map, error) { func (op *gLinkOp) One() (Map, error) {
list, err := op.All() list, err := op.All()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &(*list)[0], nil return list[0], nil
} }
// 链式操作,查询字段值 // 链式操作,查询字段值
@ -225,7 +225,7 @@ func (op *gLinkOp) Value() (interface{}, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
for _, v := range *one { for _, v := range one {
return v, nil return v, nil
} }
return "", nil return "", nil

View File

@ -1,58 +0,0 @@
// 基类
package gbase
import (
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gconsole"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/frame/gconfig"
"gitee.com/johng/gf/g/frame/ginstance"
)
// 框架基类所有的基于gf框架的类对象都继承于此以便使用框架的一些封装的核心组件
type Base struct {
Db gdb.Link // 数据库操作对象
Config *gconfig.Config // 配置管理对象
}
// 基类初始化,如若需要自定义初始化内置核心对象组件,可在继承子类中覆盖此方法
func (b *Base) Init() {
// 配置文件目录查找依次为启动参数cfgpath、当前程序运行目录
if b.Config == nil {
path := gconsole.Option.Get("cfgpath")
if path == "" {
path = gfile.SelfDir()
}
ckey := "gf_config_with_path_" + path
result := ginstance.Get(ckey)
if result != nil {
b.Config = result.(*gconfig.Config)
} else {
b.Config = gconfig.New(path)
ginstance.Set(ckey, b.Config)
}
}
// 数据库操作对象初始化
// 全局只有一个数据库单例对象,可以配置不同分组的配置进行使用
if b.Db == nil {
ckey := "gf_database"
result := ginstance.Get(ckey)
if result != nil {
b.Db = result.(gdb.Link)
} else {
if m := b.Config.GetMap("database"); m != nil {
for group, v := range m {
if list, ok := v.([]interface{}); ok {
for _, nodei := range list {
gdb.AddConfigNodeByString(group, nodei.(string))
}
}
}
if link, err := gdb.Instance(); err != nil {
b.Db = link
ginstance.Set(ckey, b.Db)
}
}
}
}
}

View File

@ -1,7 +1,21 @@
// 单例对象管理工具 // 单例对象管理工具
// 框架内置了一些核心对象并且可以通过Set和Get方法实现IoC以及对内置核心对象的自定义替换
package ginstance package ginstance
import "gitee.com/johng/gf/g/container/gmap" import (
"strconv"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gconsole"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/frame/gconfig"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/os/glog"
)
const (
FRAME_CORE_COMPONENT_NAME_CONFIG = "gf.component.config"
FRAME_CORE_COMPONENT_NAME_DATABASE = "gf.component.database"
)
// 单例对象存储器 // 单例对象存储器
var instances = gmap.NewStringInterfaceMap() var instances = gmap.NewStringInterfaceMap()
@ -14,4 +28,93 @@ func Get(k string) interface{} {
// 设置单例对象 // 设置单例对象
func Set(k string, v interface{}) { func Set(k string, v interface{}) {
instances.Set(k, v) instances.Set(k, v)
}
// 核心对象Config
// 配置文件目录查找依次为启动参数cfgpath、当前程序运行目录
func Config() *gconfig.Config {
result := Get(FRAME_CORE_COMPONENT_NAME_CONFIG)
if result != nil {
return result.(*gconfig.Config)
} else {
path := gconsole.Option.Get("cfgpath")
if path == "" {
path = gfile.SelfDir()
}
config := gconfig.New(path)
Set(FRAME_CORE_COMPONENT_NAME_CONFIG, config)
return config
}
return nil
}
// 核心对象Database
func Database(names...string) gdb.Link {
result := Get(FRAME_CORE_COMPONENT_NAME_DATABASE)
if result != nil {
return result.(gdb.Link)
} 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)
}
}
}
var db gdb.Link = nil
if len(names) == 0 {
if link, err := gdb.Instance(); err == nil {
db = link
} else {
glog.Error(err)
}
} else {
if link, err := gdb.InstanceByGroup(names[0]); err == nil {
db = link
} else {
glog.Error(err)
}
}
if db != nil {
Set(FRAME_CORE_COMPONENT_NAME_DATABASE, db)
return db
}
}
}
return nil
} }

View File

@ -3,7 +3,6 @@ package gmvc
import ( import (
"gitee.com/johng/gf/g/net/ghttp" "gitee.com/johng/gf/g/net/ghttp"
"gitee.com/johng/gf/g/frame/gbase"
"gitee.com/johng/gf/g/net/gsession" "gitee.com/johng/gf/g/net/gsession"
) )
@ -13,7 +12,6 @@ const (
// 控制器基类 // 控制器基类
type Controller struct { type Controller struct {
gbase.Base
Server *ghttp.Server // Web Server对象 Server *ghttp.Server // Web Server对象
Request *ghttp.ClientRequest // 请求数据对象 Request *ghttp.ClientRequest // 请求数据对象
Response *ghttp.ServerResponse // 返回数据对象 Response *ghttp.ServerResponse // 返回数据对象
@ -24,7 +22,6 @@ type Controller struct {
// 控制器初始化接口方法 // 控制器初始化接口方法
func (c *Controller) Init(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) { func (c *Controller) Init(s *ghttp.Server, r *ghttp.ClientRequest, w *ghttp.ServerResponse) {
c.Base.Init()
c.Server = s c.Server = s
c.Request = r c.Request = r
c.Response = w c.Response = w

View File

@ -1,8 +1,6 @@
// 模型基类 // 模型基类
package gmvc package gmvc
import "gitee.com/johng/gf/g/frame/gbase"
type Model struct { type Model struct {
gbase.Base
} }

View File

@ -4,14 +4,13 @@ import (
"sync" "sync"
"html/template" "html/template"
"gitee.com/johng/gf/g/os/gview" "gitee.com/johng/gf/g/os/gview"
"gitee.com/johng/gf/g/frame/gbase"
"gitee.com/johng/gf/g/os/gfile" "gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gconsole" "gitee.com/johng/gf/g/os/gconsole"
"gitee.com/johng/gf/g/frame/ginstance"
) )
// 视图对象(一个请求一个视图对象,用完即销毁) // 视图对象(一个请求一个视图对象,用完即销毁)
type View struct { type View struct {
gbase.Base
mu sync.RWMutex // 并发互斥锁 mu sync.RWMutex // 并发互斥锁
ctl *Controller // 所属控制器 ctl *Controller // 所属控制器
view *gview.View // 底层视图对象 view *gview.View // 底层视图对象
@ -25,8 +24,10 @@ func NewView(c *Controller) *View {
if path == "" { if path == "" {
path = gfile.SelfDir() path = gfile.SelfDir()
} }
if r := c.Config.Get("viewpath"); r != nil { if config := ginstance.Config(); config != nil {
path = r.(string) if r := config.Get("viewpath"); r != nil {
path = r.(string)
}
} }
return &View{ return &View{
ctl : c, ctl : c,
@ -52,7 +53,11 @@ func (view *View) Assign(key string, value interface{}) {
} }
// 解析指定模板 // 解析指定模板
func (view *View) Display(file string) error { func (view *View) Display(files...string) error {
file := "default"
if len(files) > 0 {
file = files[0]
}
// 查询模板 // 查询模板
tpl, err := view.view.Template(file) tpl, err := view.view.Template(file)
if err != nil { if err != nil {

View File

@ -6,7 +6,7 @@
"host" : "127.0.0.1", "host" : "127.0.0.1",
"port" : "3306", "port" : "3306",
"user" : "root", "user" : "root",
"pass" : "127456", "pass" : "123456",
"name" : "test", "name" : "test",
"type" : "mysql", "type" : "mysql",
"role" : "master", "role" : "master",
@ -17,7 +17,7 @@
"host" : "127.0.0.1", "host" : "127.0.0.1",
"port" : "3306", "port" : "3306",
"user" : "root", "user" : "root",
"pass" : "127456", "pass" : "123456",
"name" : "test", "name" : "test",
"type" : "mysql", "type" : "mysql",
"role" : "master", "role" : "master",

View File

@ -1,18 +1,11 @@
package main package main
import ( import (
"fmt" "fmt"
"os" "gitee.com/johng/gf/g/frame/ginstance"
) )
func Add(path string, name ... string) {
fmt.Println(name)
}
func main() { func main() {
for _, e := range os.Environ() { db := ginstance.Database()
list, _ := db.Table("test").Select()
fmt.Println(e) fmt.Println(list[0])
}
} }

View File

@ -1,6 +1,6 @@
package gf package gf
// 框架信息 // 框架信息
const VERSION = "0.60" const VERSION = "0.80"
const AUTHORS = "john<john@johng.cn>" const AUTHORS = "john<john@johng.cn>"