mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
new version of gdb developing
This commit is contained in:
2
TODO.MD
2
TODO.MD
@ -42,6 +42,8 @@
|
||||
1. gtcp提供简便的包发送/接收方法(SendPkg/RecvPkg)以解决常见的TCP通信粘包问题,并完善文档(参考:https://www.cnblogs.com/kex1n/p/6502002.html);
|
||||
1. gfile对于文件的读写强行使用了gfpool,在某些场景下不合适,需要考虑剥离开,并为开发者提供单独的指针池文件操作特性;
|
||||
1. 路由增加不区分大小写得匹配方式;
|
||||
1. str_ireplace: http://php.net/manual/en/function.str-ireplace.php
|
||||
1. strpos/stripos/strrpos/strripos: http://php.net/manual/en/function.stripos.php
|
||||
|
||||
|
||||
|
||||
|
||||
@ -12,12 +12,14 @@ import (
|
||||
"database/sql"
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
_ "gitee.com/johng/gf/third/github.com/go-sql-driver/mysql"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 数据库链式操作模型对象
|
||||
type Model struct {
|
||||
tx *Tx // 数据库事务对象
|
||||
db *Db // 数据库操作对象
|
||||
tablesInit string // 初始化Model时的表名称(可以是多个)
|
||||
tables string // 数据库操作表
|
||||
fields string // 操作字段
|
||||
where string // 操作条件
|
||||
@ -36,9 +38,10 @@ type Model struct {
|
||||
// 链式操作,数据表字段,可支持多个表,以半角逗号连接
|
||||
func (db *Db) Table(tables string) (*Model) {
|
||||
return &Model{
|
||||
db: db,
|
||||
tables: tables,
|
||||
fields: "*",
|
||||
db : db,
|
||||
tablesInit : tables,
|
||||
tables : tables,
|
||||
fields : "*",
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,9 +53,10 @@ func (db *Db) From(tables string) (*Model) {
|
||||
// (事务)链式操作,数据表字段,可支持多个表,以半角逗号连接
|
||||
func (tx *Tx) Table(tables string) (*Model) {
|
||||
return &Model{
|
||||
db: tx.db,
|
||||
tx: tx,
|
||||
tables: tables,
|
||||
db : tx.db,
|
||||
tx : tx,
|
||||
tablesInit : tables,
|
||||
tables : tables,
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +65,15 @@ func (tx *Tx) From(tables string) (*Model) {
|
||||
return tx.Table(tables)
|
||||
}
|
||||
|
||||
// 清空链式操作数据,以便改model可以重复使用
|
||||
func (md *Model) clear() {
|
||||
if md.tx != nil {
|
||||
*md = *md.tx.Table(md.tablesInit)
|
||||
} else {
|
||||
*md = *md.db.Table(md.tablesInit)
|
||||
}
|
||||
}
|
||||
|
||||
// 链式操作,左联表
|
||||
func (md *Model) LeftJoin(joinTable string, on string) (*Model) {
|
||||
md.tables += fmt.Sprintf(" LEFT JOIN %s ON (%s)", joinTable, on)
|
||||
@ -87,21 +100,25 @@ func (md *Model) Fields(fields string) (*Model) {
|
||||
|
||||
// 链式操作,condition,支持string & gdb.Map
|
||||
func (md *Model) Where(where interface{}, args ...interface{}) (*Model) {
|
||||
md.where = md.db.formatCondition(where)
|
||||
md.where = md.db.formatCondition(where)
|
||||
md.whereArgs = append(md.whereArgs, args...)
|
||||
// 支持 Where("uid", 1)这种格式
|
||||
if len(args) == 1 && strings.Index(md.where , "?") < 0 {
|
||||
md.where += "=?"
|
||||
}
|
||||
return md
|
||||
}
|
||||
|
||||
// 链式操作,添加AND条件到Where中
|
||||
func (md *Model) And(where interface{}, args ...interface{}) (*Model) {
|
||||
md.where += " AND " + md.db.formatCondition(where)
|
||||
md.where += " AND " + md.db.formatCondition(where)
|
||||
md.whereArgs = append(md.whereArgs, args...)
|
||||
return md
|
||||
}
|
||||
|
||||
// 链式操作,添加OR条件到Where中
|
||||
func (md *Model) Or(where interface{}, args ...interface{}) (*Model) {
|
||||
md.where += " OR " + md.db.formatCondition(where)
|
||||
md.where += " OR " + md.db.formatCondition(where)
|
||||
md.whereArgs = append(md.whereArgs, args...)
|
||||
return md
|
||||
}
|
||||
@ -153,6 +170,7 @@ func (md *Model) Insert() (result sql.Result, err error) {
|
||||
if err == nil {
|
||||
md.checkAndRemoveCache()
|
||||
}
|
||||
md.clear()
|
||||
}()
|
||||
if md.data == nil {
|
||||
return nil, errors.New("inserting into table with empty data")
|
||||
@ -184,6 +202,7 @@ func (md *Model) Replace() (result sql.Result, err error) {
|
||||
if err == nil {
|
||||
md.checkAndRemoveCache()
|
||||
}
|
||||
md.clear()
|
||||
}()
|
||||
if md.data == nil {
|
||||
return nil, errors.New("replacing into table with empty data")
|
||||
@ -215,6 +234,7 @@ func (md *Model) Save() (result sql.Result, err error) {
|
||||
if err == nil {
|
||||
md.checkAndRemoveCache()
|
||||
}
|
||||
md.clear()
|
||||
}()
|
||||
if md.data == nil {
|
||||
return nil, errors.New("replacing into table with empty data")
|
||||
@ -246,6 +266,7 @@ func (md *Model) Update() (result sql.Result, err error) {
|
||||
if err == nil {
|
||||
md.checkAndRemoveCache()
|
||||
}
|
||||
md.clear()
|
||||
}()
|
||||
if md.data == nil {
|
||||
return nil, errors.New("updating table with empty data")
|
||||
@ -263,6 +284,7 @@ func (md *Model) Delete() (result sql.Result, err error) {
|
||||
if err == nil {
|
||||
md.checkAndRemoveCache()
|
||||
}
|
||||
md.clear()
|
||||
}()
|
||||
if md.where == "" {
|
||||
return nil, errors.New("where is required while deleting")
|
||||
@ -298,6 +320,7 @@ func (md *Model) Cache(time int, name ... string) *Model {
|
||||
|
||||
// 链式操作,select
|
||||
func (md *Model) Select() (Result, error) {
|
||||
defer md.clear()
|
||||
return md.getAll(md.getFormattedSql(), md.whereArgs...)
|
||||
}
|
||||
|
||||
@ -342,6 +365,7 @@ func (md *Model) Struct(obj interface{}) error {
|
||||
// 链式操作,查询数量,fields可以为空,也可以自定义查询字段,
|
||||
// 当给定自定义查询字段时,该字段必须为数量结果,否则会引起歧义,使用如:md.Fields("COUNT(id)")
|
||||
func (md *Model) Count() (int, error) {
|
||||
defer md.clear()
|
||||
if md.fields == "" || md.fields == "*" {
|
||||
md.fields = "COUNT(1)"
|
||||
} else {
|
||||
@ -424,11 +448,11 @@ func (md *Model) getFormattedSql() string {
|
||||
// @author ymrjqyy
|
||||
// @author 2018-08-15
|
||||
func (md *Model) Chunk(limit int, callback func(result Result, err error) bool) {
|
||||
var page = 1
|
||||
defer md.clear()
|
||||
page := 1
|
||||
for {
|
||||
md.ForPage(page, limit)
|
||||
sqls := md.getFormattedSql()
|
||||
data, err := md.getAll(sqls, md.whereArgs...)
|
||||
data, err := md.getAll(md.getFormattedSql(), md.whereArgs...)
|
||||
if err != nil {
|
||||
callback(nil, err)
|
||||
break
|
||||
|
||||
10
g/g.go
10
g/g.go
@ -10,14 +10,14 @@ package g
|
||||
import "gitee.com/johng/gf/g/container/gvar"
|
||||
|
||||
// 框架动态变量,可以用该类型替代interface{}类型
|
||||
type Var = gvar.Var
|
||||
type Var = gvar.Var
|
||||
|
||||
// 常用map数据结构(使用别名)
|
||||
type Map = map[string]interface{}
|
||||
type Map = map[string]interface{}
|
||||
|
||||
// 常用list数据结构(使用别名)
|
||||
type List = []Map
|
||||
type List = []Map
|
||||
|
||||
// 常用slice数据结构(使用别名)
|
||||
type Slice = []interface{}
|
||||
type Array = Slice
|
||||
type Slice = []interface{}
|
||||
type Array = Slice
|
||||
|
||||
@ -25,7 +25,6 @@ func handleProcessSignal() {
|
||||
syscall.SIGINT,
|
||||
syscall.SIGQUIT,
|
||||
syscall.SIGKILL,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGUSR1,
|
||||
syscall.SIGUSR2,
|
||||
@ -34,7 +33,7 @@ func handleProcessSignal() {
|
||||
sig = <- procSignalChan
|
||||
switch sig {
|
||||
// 进程终止,停止所有子进程运行
|
||||
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGHUP, syscall.SIGTERM:
|
||||
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM:
|
||||
shutdownWebServers(sig.String())
|
||||
return
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 字符串替换
|
||||
// 字符串替换(大小写敏感)
|
||||
func Replace(origin, search, replace string, count...int) string {
|
||||
n := -1
|
||||
if len(count) > 0 {
|
||||
@ -22,7 +22,7 @@ func Replace(origin, search, replace string, count...int) string {
|
||||
return strings.Replace(origin, search, replace, n)
|
||||
}
|
||||
|
||||
// 使用map进行字符串替换
|
||||
// 使用map进行字符串替换(大小写敏感)
|
||||
func ReplaceByMap(origin string, replaces map[string]string) string {
|
||||
result := origin
|
||||
for k, v := range replaces {
|
||||
|
||||
@ -14,7 +14,12 @@ import (
|
||||
// 检测键值对参数Map,
|
||||
// rules参数支持 []string / map[string]string 类型,前面一种类型支持返回校验结果顺序(具体格式参考struct tag),后一种不支持;
|
||||
// rules参数中得 map[string]string 是一个2维的关联数组,第一维键名为参数键名,第二维为带有错误的校验规则名称,值为错误信息。
|
||||
func CheckMap(params map[string]interface{}, rules interface{}, msgs...CustomMsg) *Error {
|
||||
func CheckMap(params interface{}, rules interface{}, msgs...CustomMsg) *Error {
|
||||
// 将参数转换为 map[string]interface{}类型
|
||||
data := gconv.Map(params)
|
||||
if data == nil {
|
||||
return newErrorStr("invalid_params", "invalid params type: convert to map[string]interface{} failed")
|
||||
}
|
||||
// 真实校验规则数据结构
|
||||
checkRules := make(map[string]string)
|
||||
// 真实自定义错误信息数据结构
|
||||
@ -74,10 +79,10 @@ func CheckMap(params map[string]interface{}, rules interface{}, msgs...CustomMsg
|
||||
// 这里的rule变量为多条校验规则,不包含名字或者错误信息定义
|
||||
for key, rule := range checkRules {
|
||||
value = nil
|
||||
if v, ok := params[key]; ok {
|
||||
if v, ok := data[key]; ok {
|
||||
value = v
|
||||
}
|
||||
if e := Check(value, rule, customMsgs[key], params); e != nil {
|
||||
if e := Check(value, rule, customMsgs[key], data); e != nil {
|
||||
_, item := e.FirstItem()
|
||||
// 如果值为nil|"",并且不需要require*验证时,其他验证失效
|
||||
if value == nil || gconv.String(value) == "" {
|
||||
|
||||
@ -22,7 +22,7 @@ type Error struct {
|
||||
type ErrorMap map[string]map[string]string
|
||||
|
||||
|
||||
// 创建一个校验错误对象指针
|
||||
// 创建一个校验错误对象指针(校验错误)
|
||||
func newError(rules []string, errors map[string]map[string]string) *Error {
|
||||
return &Error {
|
||||
rules : rules,
|
||||
@ -30,6 +30,18 @@ func newError(rules []string, errors map[string]map[string]string) *Error {
|
||||
}
|
||||
}
|
||||
|
||||
// 创建一个校验错误对象指针(内部错误)
|
||||
func newErrorStr(key, err string) *Error {
|
||||
return &Error {
|
||||
rules : nil,
|
||||
errors : map[string]map[string]string{
|
||||
"__gvalid__" : {
|
||||
key: err,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 获得规则与错误信息的map; 当校验结果为多条数据校验时,返回第一条错误map(此时类似FirstItem)
|
||||
func (e *Error) Map() map[string]string {
|
||||
_, m := e.FirstItem()
|
||||
|
||||
@ -1,35 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/util/gvalid"
|
||||
)
|
||||
import "fmt"
|
||||
|
||||
type User struct {
|
||||
Uid int `gvalid:"uid @integer|min:1"`
|
||||
Name string `gvalid:"name @required|length:6,30#请输入用户名称|用户名称长度非法"`
|
||||
Pass1 string `gvalid:"password1@required|password3"`
|
||||
Pass2 string `gvalid:"password2@required|password3|same:password1#||两次密码不一致,请重新输入"`
|
||||
Uid int
|
||||
}
|
||||
|
||||
func New() *User {
|
||||
return &User{
|
||||
100,
|
||||
}
|
||||
}
|
||||
|
||||
func (user *User) Clear() {
|
||||
user = New()
|
||||
}
|
||||
|
||||
func main() {
|
||||
user := &User{
|
||||
Name : "john",
|
||||
Pass1: "Abc123!@#",
|
||||
Pass2: "123",
|
||||
}
|
||||
|
||||
// 使用结构体定义的校验规则和错误提示进行校验
|
||||
g.Dump(gvalid.CheckStruct(user, nil).Maps())
|
||||
|
||||
// 自定义校验规则和错误提示,对定义的特定校验规则和错误提示进行覆盖
|
||||
rules := map[string]string {
|
||||
"Uid" : "required",
|
||||
}
|
||||
msgs := map[string]interface{} {
|
||||
"Pass2" : map[string]string {
|
||||
"password3" : "名称不能为空",
|
||||
},
|
||||
}
|
||||
g.Dump(gvalid.CheckStruct(user, rules, msgs).Maps())
|
||||
user := New()
|
||||
user.Uid = 10000
|
||||
fmt.Println(user)
|
||||
user.Clear()
|
||||
fmt.Println(user)
|
||||
}
|
||||
Reference in New Issue
Block a user