diff --git a/.gitignore b/.gitignore index 93456099d..8470fac8f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ .settings/ .vscode/ vender/ -log/ composer.lock gitpush.sh pkg/ diff --git a/.travis.yml b/.travis.yml index f522ba548..5c05fa0a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,10 @@ before_install: install: - cat /etc/hosts +before_script: +- find . -name "*.go" | xargs gofmt -w +- git diff --exit-code + script: - cd g - GOARCH=386 go test -v ./... diff --git a/DONATOR.MD b/DONATOR.MD index 6a9aa30e6..efb01701c 100644 --- a/DONATOR.MD +++ b/DONATOR.MD @@ -12,9 +12,11 @@ |[zhuhuan12](https://gitee.com/zhuhuan12)|gitee|¥50.00 |[zfan_codes](https://gitee.com/zfan_codes)|gitee|¥10.00 |[arden](https://github.com/arden)|alipay|¥10.00 +|x*z|wechat|¥20.00 |潘兄|wechat|¥100.00 |Fly的狐狸|wechat|¥100.00 |土豆相公|alipay|¥66.60 +|Hades|alipay|¥66.66 |蔡蔡|wechat|¥666.00 |上海金保证网络科技|bank|¥2000.00 diff --git a/README.MD b/README.MD index 26310d175..ab18f553f 100644 --- a/README.MD +++ b/README.MD @@ -11,48 +11,35 @@ -`GF(Go Frame)`是一款模块化、高性能、生产级Go应用开发框架。提供了常用的核心开发组件,如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、数据校验、数据编码、文件监控、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、 -并发安全容器等等。并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、服务注册、配置管理、模板引擎等等,支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。 +`GF(GoFrame)` is a modular, full-featured and production-ready application development framework of golang. Providing a series of core components and dozens of practical modules, such as: memcache, configure, validator, logging, array/queue/set/map containers, timer/timing tasks, file/memory lock, object pool, database ORM, etc. Supporting web server integrated with router, cookie, session, logger, template, https, hooks, rewrites and many more features. -# 特点 -* 模块化、松耦合设计; -* 模块丰富,开箱即用; -* 详尽的开发文档及示例; -* 完善的本地中文化支持; -* 致力于项目的通用方案; -* 更适合企业及团队使用; -* 更多请查阅文档及源码; - -# 安装 -```html +# Installation +``` go get -u github.com/gogf/gf ``` -或者 -`go.mod`: +or use `go.mod`: ``` require github.com/gogf/gf latest ``` -# 限制 -```shell -golang版本 >= 1.10 +# Limitation +``` +golang version >= 1.10 ``` -# 架构 +# Documentation + +* [APIDoc](https://godoc.org/github.com/gogf/gf) +* [中文文档](https://goframe.org) + +# Architecture
+# Quick Start - -# 文档 - -开发文档:[https://goframe.org](https://goframe.org) - -接口文档:[https://godoc.org/github.com/gogf/gf](https://godoc.org/github.com/gogf/gf) - -# 使用 ```go package main @@ -70,17 +57,26 @@ func main() { } ``` -[更多..](https://goframe.org/start/index) +[View More..](https://goframe.org/start/index) -# 协议 +# License + +`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever. + +# Donators + +We currently accept donation by Alipay/WechatPay, please note your github/gitee account in your payment bill. If you like `GF`, why not [buy developer a cup of coffee](DONATOR.MD)? + +# Thanks +JetBrains + + + -`GF` 使用非常友好的 [MIT](LICENSE) 开源协议进行发布,永久`100%`开源免费。 -# 捐赠 -如果您喜欢`GF`,要不[给开发者来杯咖啡吧](DONATOR.MD)! -请在捐赠时备注您的`github`/`gitee`账号名称。 -# 感谢 -JetBrains \ No newline at end of file diff --git a/TODO.MD b/TODO.MD index c56610e9c..1f48705ae 100644 --- a/TODO.MD +++ b/TODO.MD @@ -48,6 +48,7 @@ 1. 改进gdb对pgsql/mssql/oracle的支持,使用方法覆盖的方式改进操作,而不是完全依靠正则替换的方式; 1. gdb的Cache缓存功能增加可自定义缓存接口,以便支持外部缓存功能,缓存接口可以通过io.ReadWriter接口实现; 1. grpool增加支持阻塞添加任务接口; +1. gdb.Model在链式安全的对象创建中增加sync.Pool的使用; # DONE diff --git a/g/crypto/gaes/gaes_test.go b/g/crypto/gaes/gaes_test.go index 119900065..249e99c87 100644 --- a/g/crypto/gaes/gaes_test.go +++ b/g/crypto/gaes/gaes_test.go @@ -9,20 +9,21 @@ package gaes_test import ( - "github.com/gogf/gf/g/encoding/gbase64" "testing" + "github.com/gogf/gf/g/encoding/gbase64" + "github.com/gogf/gf/g/crypto/gaes" "github.com/gogf/gf/g/test/gtest" ) var ( content = []byte("pibigstar") - content_16, _ = gbase64.Decode("v1jqsGHId/H8onlVHR8Vaw==") - content_24, _ = gbase64.Decode("0TXOaj5KMoLhNWmJ3lxY1A==") - content_32, _ = gbase64.Decode("qM/Waw1kkWhrwzek24rCSA==") - content_16_iv, _ = gbase64.Decode("DqQUXiHgW/XFb6Qs98+hrA==") - content_32_iv, _ = gbase64.Decode("ZuLgAOii+lrD5KJoQ7yQ8Q==") + content_16, _ = gbase64.DecodeString("v1jqsGHId/H8onlVHR8Vaw==") + content_24, _ = gbase64.DecodeString("0TXOaj5KMoLhNWmJ3lxY1A==") + content_32, _ = gbase64.DecodeString("qM/Waw1kkWhrwzek24rCSA==") + content_16_iv, _ = gbase64.DecodeString("DqQUXiHgW/XFb6Qs98+hrA==") + content_32_iv, _ = gbase64.DecodeString("ZuLgAOii+lrD5KJoQ7yQ8Q==") // iv 长度必须等于blockSize,只能为16 iv = []byte("Hello My GoFrame") key_16 = []byte("1234567891234567") @@ -35,7 +36,7 @@ var ( // cfb模式blockSize补位长度, add by zseeker padding_size = 16 - len(content) - content_16_cfb, _ = gbase64.Decode("oSmget3aBDT1nJnBp8u6kA==") + content_16_cfb, _ = gbase64.DecodeString("oSmget3aBDT1nJnBp8u6kA==") ) func TestEncrypt(t *testing.T) { diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index d4c14ce8c..fa30812e3 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -14,13 +14,14 @@ import ( "database/sql" "errors" "fmt" + "time" + "github.com/gogf/gf/g/container/gmap" "github.com/gogf/gf/g/container/gring" "github.com/gogf/gf/g/container/gtype" "github.com/gogf/gf/g/container/gvar" "github.com/gogf/gf/g/os/gcache" "github.com/gogf/gf/g/util/grand" - "time" ) // 数据库操作接口 diff --git a/g/database/gdb/gdb_base.go b/g/database/gdb/gdb_base.go index 21708c0ac..045d5e450 100644 --- a/g/database/gdb/gdb_base.go +++ b/g/database/gdb/gdb_base.go @@ -11,13 +11,14 @@ import ( "database/sql" "errors" "fmt" + "reflect" + "strings" + "github.com/gogf/gf/g/container/gvar" "github.com/gogf/gf/g/os/gcache" "github.com/gogf/gf/g/os/gtime" "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/util/gconv" - "reflect" - "strings" ) const ( @@ -498,7 +499,10 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt // CURD操作:数据更新,统一采用sql预处理。 // data参数支持string/map/struct/*struct类型。 func (bs *dbBase) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) { - newWhere, newArgs := formatCondition(condition, args) + newWhere, newArgs := formatWhere(condition, args) + if newWhere != "" { + newWhere = " WHERE " + newWhere + } return bs.db.doUpdate(nil, table, data, newWhere, newArgs...) } @@ -537,15 +541,15 @@ func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, conditio return nil, err } } - if len(condition) == 0 { - return bs.db.doExec(link, fmt.Sprintf("UPDATE %s SET %s", table, updates), args...) - } - return bs.db.doExec(link, fmt.Sprintf("UPDATE %s SET %s WHERE %s", table, updates, condition), args...) + return bs.db.doExec(link, fmt.Sprintf("UPDATE %s SET %s%s", table, updates, condition), args...) } // CURD操作:删除数据 func (bs *dbBase) Delete(table string, condition interface{}, args ...interface{}) (result sql.Result, err error) { - newWhere, newArgs := formatCondition(condition, args) + newWhere, newArgs := formatWhere(condition, args) + if newWhere != "" { + newWhere = " WHERE " + newWhere + } return bs.db.doDelete(nil, table, newWhere, newArgs...) } @@ -556,10 +560,7 @@ func (bs *dbBase) doDelete(link dbLink, table string, condition string, args ... return nil, err } } - if len(condition) == 0 { - return bs.db.doExec(link, fmt.Sprintf("DELETE FROM %s", table), args...) - } - return bs.db.doExec(link, fmt.Sprintf("DELETE FROM %s WHERE %s", table, condition), args...) + return bs.db.doExec(link, fmt.Sprintf("DELETE FROM %s%s", table, condition), args...) } // 获得缓存对象 @@ -570,12 +571,15 @@ func (bs *dbBase) getCache() *gcache.Cache { // 将数据查询的列表数据*sql.Rows转换为Result类型 func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) { // 列信息列表, 名称与类型 - types := make([]string, 0) - columns := make([]string, 0) - columnTypes, _ := rows.ColumnTypes() - for _, t := range columnTypes { - types = append(types, t.DatabaseTypeName()) - columns = append(columns, t.Name()) + columnTypes, err := rows.ColumnTypes() + if err != nil { + return nil, err + } + types := make([]string, len(columnTypes)) + columns := make([]string, len(columnTypes)) + for k, v := range columnTypes { + types[k] = v.DatabaseTypeName() + columns[k] = v.Name() } // 返回结构组装 values := make([]sql.RawBytes, len(columns)) @@ -589,14 +593,15 @@ func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) { return records, err } row := make(Record) - // 注意col字段是一个[]byte类型(slice类型本身是一个指针),多个记录循环时该变量指向的是同一个内存地址 - for i, col := range values { - if col == nil { + // 注意col字段是一个[]byte类型(slice类型本身是一个引用类型), + // 多个记录循环时该变量指向的是同一个内存地址 + for i, column := range values { + if column == nil { row[columns[i]] = gvar.New(nil, true) } else { // 由于 sql.RawBytes 是slice类型, 这里必须使用值复制 - v := make([]byte, len(col)) - copy(v, col) + v := make([]byte, len(column)) + copy(v, column) row[columns[i]] = gvar.New(bs.db.convertValue(v, types[i]), true) } } diff --git a/g/database/gdb/gdb_func.go b/g/database/gdb/gdb_func.go index a225719d5..e874fbb51 100644 --- a/g/database/gdb/gdb_func.go +++ b/g/database/gdb/gdb_func.go @@ -10,14 +10,15 @@ import ( "bytes" "errors" "fmt" + "reflect" + "strings" + "time" + "github.com/gogf/gf/g/os/glog" "github.com/gogf/gf/g/os/gtime" "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/text/gstr" "github.com/gogf/gf/g/util/gconv" - "reflect" - "strings" - "time" ) // Type assert api for String(). @@ -25,8 +26,8 @@ type apiString interface { String() string } -// 格式化SQL查询条件 -func formatCondition(where interface{}, args []interface{}) (newWhere string, newArgs []interface{}) { +// 格式化Where查询条件 +func formatWhere(where interface{}, args []interface{}) (newWhere string, newArgs []interface{}) { // 条件字符串处理 buffer := bytes.NewBuffer(nil) // 使用反射进行类型判断 diff --git a/g/database/gdb/gdb_model.go b/g/database/gdb/gdb_model.go index d64b43558..b9168016f 100644 --- a/g/database/gdb/gdb_model.go +++ b/g/database/gdb/gdb_model.go @@ -12,8 +12,9 @@ import ( "database/sql" "errors" "fmt" - "github.com/gogf/gf/g/util/gconv" "reflect" + + "github.com/gogf/gf/g/util/gconv" ) // 数据库链式操作模型对象 @@ -29,13 +30,13 @@ type Model struct { orderBy string // 排序语句 start int // 分页开始 limit int // 分页条数 - data interface{} // 操作记录(支持Map/List/string类型) + data interface{} // 操作数据(注意仅支持Map/List/string类型) batch int // 批量操作条数 filter bool // 是否按照表字段过滤data参数 cacheEnabled bool // 当前SQL操作是否开启查询缓存功能 cacheTime int // 查询缓存时间 cacheName string // 查询缓存名称 - safe bool // 当前模型是否运行安全模式(可修改当前模型,否则每一次链式操作都是返回新的模型对象) + safe bool // 当前模型是否安全模式(默认非安全表示链式操作直接修改当前模型属性;否则每一次链式操作都是返回新的模型对象) } // 链式操作,数据表字段,可支持多个表,以半角逗号连接 @@ -45,6 +46,7 @@ func (bs *dbBase) Table(tables string) *Model { tablesInit: tables, tables: tables, fields: "*", + start: -1, safe: false, } } @@ -149,7 +151,7 @@ func (md *Model) Where(where interface{}, args ...interface{}) *Model { if model.where != "" { return md.And(where, args...) } - newWhere, newArgs := formatCondition(where, args) + newWhere, newArgs := formatWhere(where, args) model.where = newWhere model.whereArgs = newArgs return model @@ -158,7 +160,7 @@ func (md *Model) Where(where interface{}, args ...interface{}) *Model { // 链式操作,添加AND条件到Where中 func (md *Model) And(where interface{}, args ...interface{}) *Model { model := md.getModel() - newWhere, newArgs := formatCondition(where, args) + newWhere, newArgs := formatWhere(where, args) if len(model.where) > 0 && model.where[0] == '(' { model.where = fmt.Sprintf(`%s AND (%s)`, model.where, newWhere) } else { @@ -171,7 +173,7 @@ func (md *Model) And(where interface{}, args ...interface{}) *Model { // 链式操作,添加OR条件到Where中 func (md *Model) Or(where interface{}, args ...interface{}) *Model { model := md.getModel() - newWhere, newArgs := formatCondition(where, args) + newWhere, newArgs := formatWhere(where, args) if len(model.where) > 0 && model.where[0] == '(' { model.where = fmt.Sprintf(`%s OR (%s)`, model.where, newWhere) } else { @@ -195,11 +197,20 @@ func (md *Model) OrderBy(orderBy string) *Model { return model } -// 链式操作,limit -func (md *Model) Limit(start int, limit int) *Model { +// 链式操作,limit。 +// +// 如果给定一个参数,那么生成的SQL为:LIMIT limit[0] +// +// 如果给定两个参数,那么生成的SQL为:LIMIT limit[0], limit[1] +func (md *Model) Limit(limit ...int) *Model { model := md.getModel() - model.start = start - model.limit = limit + switch len(limit) { + case 1: + model.limit = limit[0] + case 2: + model.start = limit[0] + model.limit = limit[1] + } return model } @@ -425,9 +436,9 @@ func (md *Model) Update() (result sql.Result, err error) { } } if md.tx == nil { - return md.db.doUpdate(nil, md.tables, md.data, md.where, md.whereArgs...) + return md.db.doUpdate(nil, md.tables, md.data, md.getConditionSql(), md.whereArgs...) } else { - return md.tx.doUpdate(md.tables, md.data, md.where, md.whereArgs...) + return md.tx.doUpdate(md.tables, md.data, md.getConditionSql(), md.whereArgs...) } } @@ -439,9 +450,9 @@ func (md *Model) Delete() (result sql.Result, err error) { } }() if md.tx == nil { - return md.db.doDelete(nil, md.tables, md.where, md.whereArgs...) + return md.db.doDelete(nil, md.tables, md.getConditionSql(), md.whereArgs...) } else { - return md.tx.doDelete(md.tables, md.where, md.whereArgs...) + return md.tx.doDelete(md.tables, md.getConditionSql(), md.whereArgs...) } } @@ -452,7 +463,7 @@ func (md *Model) Select() (Result, error) { // 链式操作,查询所有记录 func (md *Model) All() (Result, error) { - return md.getAll(md.getFormattedSql(), md.whereArgs...) + return md.getAll(fmt.Sprintf("SELECT %s FROM %s %s", md.fields, md.tables, md.getConditionSql()), md.whereArgs...) } // 链式操作,查询单条记录 @@ -530,7 +541,7 @@ func (md *Model) Count() (int, error) { } else { md.fields = fmt.Sprintf(`COUNT(%s)`, md.fields) } - s := md.getFormattedSql() + s := fmt.Sprintf("SELECT %s FROM %s %s", md.fields, md.tables, md.getConditionSql()) if len(md.groupBy) > 0 { s = fmt.Sprintf("SELECT COUNT(1) FROM (%s) count_alias", s) } @@ -583,12 +594,9 @@ func (md *Model) checkAndRemoveCache() { } } -// 格式化当前输入参数,返回可执行的SQL语句(不带参数) -func (md *Model) getFormattedSql() string { - if md.fields == "" { - md.fields = "*" - } - s := fmt.Sprintf("SELECT %s FROM %s", md.fields, md.tables) +// 格式化当前输入参数,返回SQL条件语句(不带参数) +func (md *Model) getConditionSql() string { + s := "" if md.where != "" { s += " WHERE " + md.where } @@ -599,7 +607,12 @@ func (md *Model) getFormattedSql() string { s += " ORDER BY " + md.orderBy } if md.limit != 0 { - s += fmt.Sprintf(" LIMIT %d, %d", md.start, md.limit) + if md.start >= 0 { + s += fmt.Sprintf(" LIMIT %d, %d", md.start, md.limit) + } else { + s += fmt.Sprintf(" LIMIT %d", md.limit) + } + } return s } diff --git a/g/database/gdb/gdb_transaction.go b/g/database/gdb/gdb_transaction.go index 84922f10b..b91cac7c5 100644 --- a/g/database/gdb/gdb_transaction.go +++ b/g/database/gdb/gdb_transaction.go @@ -9,8 +9,9 @@ package gdb import ( "database/sql" "fmt" - "github.com/gogf/gf/g/text/gregex" "reflect" + + "github.com/gogf/gf/g/text/gregex" ) // 数据库事务对象 @@ -164,7 +165,10 @@ func (tx *TX) BatchSave(table string, list interface{}, batch ...int) (sql.Resul // CURD操作:数据更新,统一采用sql预处理, // data参数支持字符串或者关联数组类型,内部会自行做判断处理. func (tx *TX) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) { - newWhere, newArgs := formatCondition(condition, args) + newWhere, newArgs := formatWhere(condition, args) + if newWhere != "" { + newWhere = " WHERE " + newWhere + } return tx.doUpdate(table, data, newWhere, newArgs...) } @@ -175,7 +179,10 @@ func (tx *TX) doUpdate(table string, data interface{}, condition string, args .. // CURD操作:删除数据 func (tx *TX) Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) { - newWhere, newArgs := formatCondition(condition, args) + newWhere, newArgs := formatWhere(condition, args) + if newWhere != "" { + newWhere = " WHERE " + newWhere + } return tx.doDelete(table, newWhere, newArgs...) } diff --git a/g/database/gdb/gdb_unit_init_test.go b/g/database/gdb/gdb_unit_init_test.go index 4121438ef..223c2ed20 100644 --- a/g/database/gdb/gdb_unit_init_test.go +++ b/g/database/gdb/gdb_unit_init_test.go @@ -8,12 +8,14 @@ package gdb_test import ( "fmt" + "os" + "github.com/gogf/gf/g" "github.com/gogf/gf/g/container/garray" + "github.com/gogf/gf/g/database/gdb" "github.com/gogf/gf/g/os/gtime" "github.com/gogf/gf/g/test/gtest" - "os" ) const ( @@ -88,14 +90,6 @@ func createTable(table ...string) (name string) { return } -// 删除指定表. -func dropTable(table string) { - if _, err := db.Exec(fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)); err != nil { - gtest.Fatal(err) - } -} - -// See createTable. // 创建测试表,并初始化默认数据。 func createInitTable(table ...string) (name string) { name = createTable(table...) @@ -117,3 +111,10 @@ func createInitTable(table ...string) (name string) { gtest.Assert(n, INIT_DATA_SIZE) return } + +// 删除指定表. +func dropTable(table string) { + if _, err := db.Exec(fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)); err != nil { + gtest.Fatal(err) + } +} diff --git a/g/database/gdb/gdb_unit_model_test.go b/g/database/gdb/gdb_unit_model_test.go index 55067785e..9422a6c53 100644 --- a/g/database/gdb/gdb_unit_model_test.go +++ b/g/database/gdb/gdb_unit_model_test.go @@ -7,10 +7,11 @@ package gdb_test import ( + "testing" + "github.com/gogf/gf/g" "github.com/gogf/gf/g/os/gtime" "github.com/gogf/gf/g/test/gtest" - "testing" ) // 基本测试 @@ -187,6 +188,25 @@ func TestModel_Save(t *testing.T) { } func TestModel_Update(t *testing.T) { + table := createInitTable() + // UPDATE...LIMIT + gtest.Case(t, func() { + result, err := db.Table(table).Data("nickname", "T100").OrderBy("id desc").Limit(2).Update() + if err != nil { + gtest.Fatal(err) + } + n, _ := result.RowsAffected() + gtest.Assert(n, 2) + + v1, err := db.Table(table).Fields("nickname").Where("id", 10).Value() + gtest.Assert(err, nil) + gtest.Assert(v1.String(), "T100") + + v2, err := db.Table(table).Fields("nickname").Where("id", 8).Value() + gtest.Assert(err, nil) + gtest.Assert(v2.String(), "T8") + }) + gtest.Case(t, func() { result, err := db.Table("user").Data("passport", "t22").Where("passport=?", "t2").Update() if err != nil { @@ -644,10 +664,22 @@ func TestModel_Where(t *testing.T) { } func TestModel_Delete(t *testing.T) { - result, err := db.Table("user").Delete() - if err != nil { - gtest.Fatal(err) - } - n, _ := result.RowsAffected() - gtest.Assert(n, 3) + // DELETE...LIMIT + gtest.Case(t, func() { + result, err := db.Table("user").Limit(2).Delete() + if err != nil { + gtest.Fatal(err) + } + n, _ := result.RowsAffected() + gtest.Assert(n, 2) + }) + + gtest.Case(t, func() { + result, err := db.Table("user").Delete() + if err != nil { + gtest.Fatal(err) + } + n, _ := result.RowsAffected() + gtest.Assert(n, 1) + }) } diff --git a/g/encoding/gbase64/gbase64.go b/g/encoding/gbase64/gbase64.go index 1ed8e92ab..e19733002 100644 --- a/g/encoding/gbase64/gbase64.go +++ b/g/encoding/gbase64/gbase64.go @@ -4,20 +4,36 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package gbase64 provides useful API for BASE64 encoding/decoding algorithms. +// Package gbase64 provides useful API for BASE64 encoding/decoding algorithm. package gbase64 import ( "encoding/base64" ) -// base64 encode -func Encode(str string) string { - return base64.StdEncoding.EncodeToString([]byte(str)) +// Encode encodes bytes with BASE64 algorithm. +func Encode(src []byte) []byte { + dst := make([]byte, base64.StdEncoding.EncodedLen(len(src))) + base64.StdEncoding.Encode(dst, src) + return dst } -// base64 decode -func Decode(str string) (string, error) { - s, e := base64.StdEncoding.DecodeString(str) - return string(s), e +// Decode decodes bytes with BASE64 algorithm. +func Decode(dst []byte) ([]byte, error) { + src := make([]byte, base64.StdEncoding.DecodedLen(len(dst))) + n, err := base64.StdEncoding.Decode(src, dst) + if err != nil { + return nil, err + } + return src[:n], nil +} + +// EncodeString encodes bytes with BASE64 algorithm. +func EncodeString(src []byte) string { + return string(Encode(src)) +} + +// DecodeString decodes string with BASE64 algorithm. +func DecodeString(str string) ([]byte, error) { + return Decode([]byte(str)) } diff --git a/g/encoding/gbase64/gbase64_test.go b/g/encoding/gbase64/gbase64_test.go index 0d6afb304..5e6cb4e91 100644 --- a/g/encoding/gbase64/gbase64_test.go +++ b/g/encoding/gbase64/gbase64_test.go @@ -6,9 +6,10 @@ package gbase64_test import ( + "testing" + "github.com/gogf/gf/g/encoding/gbase64" "github.com/gogf/gf/g/test/gtest" - "testing" ) type testpair struct { @@ -42,10 +43,17 @@ var pairs = []testpair{ } func TestBase64(t *testing.T) { - for k := range pairs { - gtest.Assert(gbase64.Encode(pairs[k].decoded), pairs[k].encoded) + gtest.Case(t, func() { + for k := range pairs { + // []byte + gtest.Assert(gbase64.Encode([]byte(pairs[k].decoded)), []byte(pairs[k].encoded)) + e1, _ := gbase64.Decode([]byte(pairs[k].encoded)) + gtest.Assert(e1, []byte(pairs[k].decoded)) - e, _ := gbase64.Decode(pairs[k].encoded) - gtest.Assert(e, pairs[k].decoded) - } + // string + gtest.Assert(gbase64.EncodeString([]byte(pairs[k].decoded)), pairs[k].encoded) + e2, _ := gbase64.DecodeString(pairs[k].encoded) + gtest.Assert(e2, []byte(pairs[k].decoded)) + } + }) } diff --git a/g/net/ghttp/ghttp_client_request.go b/g/net/ghttp/ghttp_client_request.go index ec629715c..70b6cfba8 100644 --- a/g/net/ghttp/ghttp_client_request.go +++ b/g/net/ghttp/ghttp_client_request.go @@ -14,13 +14,14 @@ import ( "encoding/json" "errors" "fmt" - "github.com/gogf/gf/g/os/gfile" "io" "mime/multipart" "net/http" "os" "strings" "time" + + "github.com/gogf/gf/g/os/gfile" ) // http客户端 @@ -82,7 +83,7 @@ func (c *Client) Put(url string, data ...interface{}) (*ClientResponse, error) { // POST请求提交数据,默认使用表单方式提交数据(绝大部分场景下也是如此)。 // 如果服务端对Content-Type有要求,可使用Client对象进行请求,单独设置相关属性。 // 支持文件上传,需要字段格式为:FieldName=@file: -func (c *Client) Post(url string, data ...interface{}) (*ClientResponse, error) { +func (c *Client) Post(url string, data ...interface{}) (resp *ClientResponse, err error) { if len(c.prefix) > 0 { url = c.prefix + url } @@ -119,23 +120,27 @@ func (c *Client) Post(url string, data ...interface{}) (*ClientResponse, error) } } writer.Close() - if r, err := http.NewRequest("POST", url, buffer); err != nil { + if req, err = http.NewRequest("POST", url, buffer); err != nil { return nil, err } else { - req = r req.Header.Set("Content-Type", writer.FormDataContentType()) } } else { - // 识别提交数据格式 + // 普通请求 paramBytes := []byte(param) - if r, err := http.NewRequest("POST", url, bytes.NewReader(paramBytes)); err != nil { + if req, err = http.NewRequest("POST", url, bytes.NewReader(paramBytes)); err != nil { return nil, err } else { - req = r - if json.Valid(paramBytes) { - req.Header.Set("Content-Type", "application/json") + if v, ok := c.header["Content-Type"]; ok { + // 自定义请求类型 + req.Header.Set("Content-Type", v) } else { - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + // 识别提交数据格式 + if json.Valid(paramBytes) { + req.Header.Set("Content-Type", "application/json") + } else { + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } } } } @@ -163,23 +168,22 @@ func (c *Client) Post(url string, data ...interface{}) (*ClientResponse, error) req.SetBasicAuth(c.authUser, c.authPass) } // 执行请求 - resp := (*http.Response)(nil) + r := (*http.Response)(nil) for { - if r, err := c.Do(req); err != nil { + if r, err = c.Do(req); err != nil { if c.retryCount > 0 { c.retryCount-- } else { return nil, err } } else { - resp = r break } } - r := &ClientResponse{ + resp = &ClientResponse{ cookies: make(map[string]string), } - r.Response = resp + resp.Response = r // 浏览器模式 if c.browserMode { now := time.Now() @@ -191,7 +195,7 @@ func (c *Client) Post(url string, data ...interface{}) (*ClientResponse, error) } } } - return r, nil + return resp, nil } // DELETE请求 diff --git a/g/net/ghttp/ghttp_request_auth.go b/g/net/ghttp/ghttp_request_auth.go index 219c2c391..a097f4327 100644 --- a/g/net/ghttp/ghttp_request_auth.go +++ b/g/net/ghttp/ghttp_request_auth.go @@ -8,9 +8,10 @@ package ghttp import ( "fmt" - "github.com/gogf/gf/g/encoding/gbase64" "net/http" "strings" + + "github.com/gogf/gf/g/encoding/gbase64" ) // 设置Basic Auth校验提示 @@ -40,12 +41,12 @@ func (r *Request) BasicAuth(user, pass string, tips ...string) bool { } switch authArray[0] { case "Basic": - authStr, err := gbase64.Decode(authArray[1]) + authBytes, err := gbase64.DecodeString(authArray[1]) if err != nil { r.Response.WriteStatus(http.StatusForbidden, err.Error()) return false } - authArray := strings.SplitN(string(authStr), ":", 2) + authArray := strings.SplitN(string(authBytes), ":", 2) if len(authArray) != 2 { r.Response.WriteStatus(http.StatusForbidden) return false diff --git a/g/net/ghttp/ghttp_response_cors.go b/g/net/ghttp/ghttp_response_cors.go index 708cfed8d..d5dcc9d36 100644 --- a/g/net/ghttp/ghttp_response_cors.go +++ b/g/net/ghttp/ghttp_response_cors.go @@ -8,7 +8,6 @@ package ghttp import ( - "github.com/gogf/gf/g/text/gstr" "github.com/gogf/gf/g/util/gconv" ) @@ -26,7 +25,7 @@ type CORSOptions struct { // 默认的CORS配置 func (r *Response) DefaultCORSOptions() CORSOptions { return CORSOptions{ - AllowOrigin: gstr.TrimRight(r.request.Referer(), "/"), + AllowOrigin: "*", AllowMethods: HTTP_METHODS, AllowCredentials: "true", MaxAge: 3628800, diff --git a/g/net/ghttp/ghttp_server_router_group.go b/g/net/ghttp/ghttp_server_router_group.go index ee65be8cf..be919e0d0 100644 --- a/g/net/ghttp/ghttp_server_router_group.go +++ b/g/net/ghttp/ghttp_server_router_group.go @@ -8,10 +8,11 @@ package ghttp import ( - "github.com/gogf/gf/g/os/glog" - "github.com/gogf/gf/g/util/gconv" "reflect" "strings" + + "github.com/gogf/gf/g/os/glog" + "github.com/gogf/gf/g/util/gconv" ) // 分组路由对象 @@ -55,10 +56,16 @@ func (g *RouterGroup) Bind(items []GroupItem) { if strings.EqualFold(gconv.String(item[0]), "REST") { g.bind("REST", gconv.String(item[0])+":"+gconv.String(item[1]), item[2]) } else { - if len(item) > 3 { - g.bind("HANDLER", gconv.String(item[0])+":"+gconv.String(item[1]), item[2], item[3]) + method := gconv.String(item[0]) + if strings.EqualFold(method, "ALL") { + method = "" } else { - g.bind("HANDLER", gconv.String(item[0])+":"+gconv.String(item[1]), item[2]) + method += ":" + } + if len(item) > 3 { + g.bind("HANDLER", method+gconv.String(item[1]), item[2], item[3]) + } else { + g.bind("HANDLER", method+gconv.String(item[1]), item[2]) } } } @@ -126,10 +133,10 @@ func (g *RouterGroup) bind(bindType string, pattern string, object interface{}, if err != nil { glog.Fatalf("invalid pattern: %s", pattern) } - if bindType == "HANDLER" { - pattern = g.server.serveHandlerKey(method, g.prefix+"/"+strings.TrimLeft(path, "/"), domain) - } else { + if bindType == "REST" { pattern = g.prefix + "/" + strings.TrimLeft(path, "/") + } else { + pattern = g.server.serveHandlerKey(method, g.prefix+"/"+strings.TrimLeft(path, "/"), domain) } } methods := gconv.Strings(params) diff --git a/g/net/ghttp/ghttp_server_router_serve.go b/g/net/ghttp/ghttp_server_router_serve.go index fe63ebf2a..9b4180686 100644 --- a/g/net/ghttp/ghttp_server_router_serve.go +++ b/g/net/ghttp/ghttp_server_router_serve.go @@ -9,8 +9,9 @@ package ghttp import ( "container/list" - "github.com/gogf/gf/g/text/gregex" "strings" + + "github.com/gogf/gf/g/text/gregex" ) // 查询请求处理方法. @@ -117,5 +118,8 @@ func (s *Server) searchServeHandler(method, path, domain string) *handlerParsedI // 生成回调方法查询的Key func (s *Server) serveHandlerKey(method, path, domain string) string { + if method == "" { + return path + "@" + strings.ToLower(domain) + } return strings.ToUpper(method) + ":" + path + "@" + strings.ToLower(domain) } diff --git a/g/net/ghttp/ghttp_server_service_controller.go b/g/net/ghttp/ghttp_server_service_controller.go index b8a344416..f50e7d990 100644 --- a/g/net/ghttp/ghttp_server_service_controller.go +++ b/g/net/ghttp/ghttp_server_service_controller.go @@ -9,18 +9,29 @@ package ghttp import ( "fmt" + "reflect" + "strings" + "github.com/gogf/gf/g/os/gfile" "github.com/gogf/gf/g/os/glog" "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/text/gstr" - "reflect" - "strings" ) // 绑定控制器,控制器需要实现 gmvc.Controller 接口, // 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话, // 第三个参数methods用以指定需要注册的方法,支持多个方法名称,多个方法以英文“,”号分隔,区分大小写. func (s *Server) BindController(pattern string, c Controller, methods ...string) { + // 当pattern中的method为all时,去掉该method,以便于后续方法判断 + domain, method, path, err := s.parsePattern(pattern) + if err != nil { + glog.Error(err) + return + } + if strings.EqualFold(method, gDEFAULT_METHOD) { + pattern = s.serveHandlerKey("", path, domain) + } + methodMap := (map[string]bool)(nil) if len(methods) > 0 { methodMap = make(map[string]bool) diff --git a/g/net/ghttp/ghttp_server_service_object.go b/g/net/ghttp/ghttp_server_service_object.go index 99d230439..cf63368b1 100644 --- a/g/net/ghttp/ghttp_server_service_object.go +++ b/g/net/ghttp/ghttp_server_service_object.go @@ -9,17 +9,28 @@ package ghttp import ( "fmt" + "reflect" + "strings" + "github.com/gogf/gf/g/os/gfile" "github.com/gogf/gf/g/os/glog" "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/text/gstr" - "reflect" - "strings" ) // 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面 // 第三个参数methods用以指定需要注册的方法,支持多个方法名称,多个方法以英文“,”号分隔,区分大小写 func (s *Server) BindObject(pattern string, obj interface{}, methods ...string) { + // 当pattern中的method为all时,去掉该method,以便于后续方法判断 + domain, method, path, err := s.parsePattern(pattern) + if err != nil { + glog.Error(err) + return + } + if strings.EqualFold(method, gDEFAULT_METHOD) { + pattern = s.serveHandlerKey("", path, domain) + } + methodMap := (map[string]bool)(nil) if len(methods) > 0 { methodMap = make(map[string]bool) diff --git a/g/os/gcache/gcache_mem_cache.go b/g/os/gcache/gcache_mem_cache.go index fcdee9716..edb648c10 100644 --- a/g/os/gcache/gcache_mem_cache.go +++ b/g/os/gcache/gcache_mem_cache.go @@ -7,14 +7,15 @@ package gcache import ( + "math" + "sync" + "github.com/gogf/gf/g/container/glist" "github.com/gogf/gf/g/container/gset" "github.com/gogf/gf/g/container/gtype" "github.com/gogf/gf/g/os/gtime" "github.com/gogf/gf/g/os/gtimer" "github.com/gogf/gf/g/util/gconv" - "math" - "sync" ) // Internal cache object. @@ -121,8 +122,8 @@ func (c *memCache) Set(key interface{}, value interface{}, expire int) { func (c *memCache) doSetWithLockCheck(key interface{}, value interface{}, expire int) interface{} { expireTimestamp := c.getInternalExpire(expire) c.dataMu.Lock() + defer c.dataMu.Unlock() if v, ok := c.data[key]; ok && !v.IsExpired() { - c.dataMu.Unlock() return v.v } if f, ok := value.(func() interface{}); ok { @@ -132,7 +133,6 @@ func (c *memCache) doSetWithLockCheck(key interface{}, value interface{}, expire return nil } c.data[key] = memCacheItem{v: value, e: expireTimestamp} - c.dataMu.Unlock() c.eventList.PushBack(&memCacheEvent{k: key, e: expireTimestamp}) return value } diff --git a/g/os/gflock/gflock_unit_test.go b/g/os/gflock/gflock_unit_test.go index e24bbdee7..689f0a921 100644 --- a/g/os/gflock/gflock_unit_test.go +++ b/g/os/gflock/gflock_unit_test.go @@ -3,6 +3,7 @@ // 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://github.com/gogf/gf. + package gflock_test import ( diff --git a/g/os/gfsnotify/gfsnotify.go b/g/os/gfsnotify/gfsnotify.go index 15c3c1257..c51ec0041 100644 --- a/g/os/gfsnotify/gfsnotify.go +++ b/g/os/gfsnotify/gfsnotify.go @@ -12,6 +12,7 @@ package gfsnotify import ( "errors" "fmt" + "github.com/gogf/gf/g/container/glist" "github.com/gogf/gf/g/container/gmap" "github.com/gogf/gf/g/container/gqueue" @@ -92,7 +93,7 @@ func New() (*Watcher, error) { return w, nil } -// 添加对指定文件/目录的监听,并给定回调函数;如果给定的是一个目录,默认非递归监控。 +// 添加对指定文件/目录的监听,并给定回调函数;如果给定的是一个目录,默认递归监控。 func Add(path string, callbackFunc func(event *Event), recursive ...bool) (callback *Callback, err error) { return defaultWatcher.Add(path, callbackFunc, recursive...) } diff --git a/g/os/gfsnotify/gfsnotify_watcher.go b/g/os/gfsnotify/gfsnotify_watcher.go index 1e9b99562..0e153d42d 100644 --- a/g/os/gfsnotify/gfsnotify_watcher.go +++ b/g/os/gfsnotify/gfsnotify_watcher.go @@ -9,10 +9,11 @@ package gfsnotify import ( "errors" "fmt" + "github.com/gogf/gf/g/container/glist" ) -// 添加监控,path参数支持文件或者目录路径,recursive为非必需参数,默认为非递归监控(当path为目录时)。 +// 添加监控,path参数支持文件或者目录路径,recursive为非必需参数,默认为递归监控(当path为目录时)。 // 如果添加目录,这里只会返回目录的callback,按照callback删除时会递归删除。 func (w *Watcher) Add(path string, callbackFunc func(event *Event), recursive ...bool) (callback *Callback, err error) { // 首先添加这个文件/目录 diff --git a/g/util/gconv/gconv_z_all_test.go b/g/util/gconv/gconv_z_all_test.go new file mode 100644 index 000000000..d0a92d3f1 --- /dev/null +++ b/g/util/gconv/gconv_z_all_test.go @@ -0,0 +1,1368 @@ +package gconv_test + +import ( + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/os/gtime" + "github.com/gogf/gf/g/test/gtest" + "github.com/gogf/gf/g/util/gconv" + "testing" + "time" +) + +type apiString interface { + String() string +} +type S struct { +} + +func (s S) String() string { + return "22222" +} + +type apiError interface { + Error() string +} +type S1 struct { +} + +func (s1 S1) Error() string { + return "22222" +} + +func Test_Bool_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.AssertEQ(gconv.Bool(i), false) + gtest.AssertEQ(gconv.Bool(false), false) + gtest.AssertEQ(gconv.Bool(nil), false) + gtest.AssertEQ(gconv.Bool(0), false) + gtest.AssertEQ(gconv.Bool("0"), false) + gtest.AssertEQ(gconv.Bool(""), false) + gtest.AssertEQ(gconv.Bool("false"), false) + gtest.AssertEQ(gconv.Bool("off"), false) + gtest.AssertEQ(gconv.Bool([]byte{}), false) + gtest.AssertEQ(gconv.Bool([]string{}), false) + gtest.AssertEQ(gconv.Bool([2]int{1, 2}), true) + gtest.AssertEQ(gconv.Bool([]interface{}{}), false) + gtest.AssertEQ(gconv.Bool([]map[int]int{}), false) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Bool(countryCapitalMap), true) + + gtest.AssertEQ(gconv.Bool("1"), true) + gtest.AssertEQ(gconv.Bool("on"), true) + gtest.AssertEQ(gconv.Bool(1), true) + gtest.AssertEQ(gconv.Bool(123.456), true) + gtest.AssertEQ(gconv.Bool(boolStruct{}), true) + gtest.AssertEQ(gconv.Bool(&boolStruct{}), true) + }) +} + +func Test_Int_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.AssertEQ(gconv.Int(i), 0) + gtest.AssertEQ(gconv.Int(false), 0) + gtest.AssertEQ(gconv.Int(nil), 0) + gtest.Assert(gconv.Int(nil), 0) + gtest.AssertEQ(gconv.Int(0), 0) + gtest.AssertEQ(gconv.Int("0"), 0) + gtest.AssertEQ(gconv.Int(""), 0) + gtest.AssertEQ(gconv.Int("false"), 0) + gtest.AssertEQ(gconv.Int("off"), 0) + gtest.AssertEQ(gconv.Int([]byte{}), 0) + gtest.AssertEQ(gconv.Int([]string{}), 0) + gtest.AssertEQ(gconv.Int([2]int{1, 2}), 0) + gtest.AssertEQ(gconv.Int([]interface{}{}), 0) + gtest.AssertEQ(gconv.Int([]map[int]int{}), 0) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Int(countryCapitalMap), 0) + + gtest.AssertEQ(gconv.Int("1"), 1) + gtest.AssertEQ(gconv.Int("on"), 0) + gtest.AssertEQ(gconv.Int(1), 1) + gtest.AssertEQ(gconv.Int(123.456), 123) + gtest.AssertEQ(gconv.Int(boolStruct{}), 0) + gtest.AssertEQ(gconv.Int(&boolStruct{}), 0) + }) +} + +func Test_Int8_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Int8(i), int8(0)) + gtest.AssertEQ(gconv.Int8(false), int8(0)) + gtest.AssertEQ(gconv.Int8(nil), int8(0)) + gtest.AssertEQ(gconv.Int8(0), int8(0)) + gtest.AssertEQ(gconv.Int8("0"), int8(0)) + gtest.AssertEQ(gconv.Int8(""), int8(0)) + gtest.AssertEQ(gconv.Int8("false"), int8(0)) + gtest.AssertEQ(gconv.Int8("off"), int8(0)) + gtest.AssertEQ(gconv.Int8([]byte{}), int8(0)) + gtest.AssertEQ(gconv.Int8([]string{}), int8(0)) + gtest.AssertEQ(gconv.Int8([2]int{1, 2}), int8(0)) + gtest.AssertEQ(gconv.Int8([]interface{}{}), int8(0)) + gtest.AssertEQ(gconv.Int8([]map[int]int{}), int8(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Int8(countryCapitalMap), int8(0)) + + gtest.AssertEQ(gconv.Int8("1"), int8(1)) + gtest.AssertEQ(gconv.Int8("on"), int8(0)) + gtest.AssertEQ(gconv.Int8(int8(1)), int8(1)) + gtest.AssertEQ(gconv.Int8(123.456), int8(123)) + gtest.AssertEQ(gconv.Int8(boolStruct{}), int8(0)) + gtest.AssertEQ(gconv.Int8(&boolStruct{}), int8(0)) + }) +} + +func Test_Int16_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Int16(i), int16(0)) + gtest.AssertEQ(gconv.Int16(false), int16(0)) + gtest.AssertEQ(gconv.Int16(nil), int16(0)) + gtest.AssertEQ(gconv.Int16(0), int16(0)) + gtest.AssertEQ(gconv.Int16("0"), int16(0)) + gtest.AssertEQ(gconv.Int16(""), int16(0)) + gtest.AssertEQ(gconv.Int16("false"), int16(0)) + gtest.AssertEQ(gconv.Int16("off"), int16(0)) + gtest.AssertEQ(gconv.Int16([]byte{}), int16(0)) + gtest.AssertEQ(gconv.Int16([]string{}), int16(0)) + gtest.AssertEQ(gconv.Int16([2]int{1, 2}), int16(0)) + gtest.AssertEQ(gconv.Int16([]interface{}{}), int16(0)) + gtest.AssertEQ(gconv.Int16([]map[int]int{}), int16(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Int16(countryCapitalMap), int16(0)) + + gtest.AssertEQ(gconv.Int16("1"), int16(1)) + gtest.AssertEQ(gconv.Int16("on"), int16(0)) + gtest.AssertEQ(gconv.Int16(int16(1)), int16(1)) + gtest.AssertEQ(gconv.Int16(123.456), int16(123)) + gtest.AssertEQ(gconv.Int16(boolStruct{}), int16(0)) + gtest.AssertEQ(gconv.Int16(&boolStruct{}), int16(0)) + }) +} + +func Test_Int32_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Int32(i), int32(0)) + gtest.AssertEQ(gconv.Int32(false), int32(0)) + gtest.AssertEQ(gconv.Int32(nil), int32(0)) + gtest.AssertEQ(gconv.Int32(0), int32(0)) + gtest.AssertEQ(gconv.Int32("0"), int32(0)) + gtest.AssertEQ(gconv.Int32(""), int32(0)) + gtest.AssertEQ(gconv.Int32("false"), int32(0)) + gtest.AssertEQ(gconv.Int32("off"), int32(0)) + gtest.AssertEQ(gconv.Int32([]byte{}), int32(0)) + gtest.AssertEQ(gconv.Int32([]string{}), int32(0)) + gtest.AssertEQ(gconv.Int32([2]int{1, 2}), int32(0)) + gtest.AssertEQ(gconv.Int32([]interface{}{}), int32(0)) + gtest.AssertEQ(gconv.Int32([]map[int]int{}), int32(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Int32(countryCapitalMap), int32(0)) + + gtest.AssertEQ(gconv.Int32("1"), int32(1)) + gtest.AssertEQ(gconv.Int32("on"), int32(0)) + gtest.AssertEQ(gconv.Int32(int32(1)), int32(1)) + gtest.AssertEQ(gconv.Int32(123.456), int32(123)) + gtest.AssertEQ(gconv.Int32(boolStruct{}), int32(0)) + gtest.AssertEQ(gconv.Int32(&boolStruct{}), int32(0)) + }) +} + +func Test_Int64_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.AssertEQ(gconv.Int64("0x00e"), int64(14)) + gtest.Assert(gconv.Int64("022"), int64(18)) + + gtest.Assert(gconv.Int64(i), int64(0)) + gtest.Assert(gconv.Int64(true), 1) + gtest.Assert(gconv.Int64("1"), int64(1)) + gtest.Assert(gconv.Int64("0"), int64(0)) + gtest.Assert(gconv.Int64("X"), int64(0)) + gtest.Assert(gconv.Int64("x"), int64(0)) + gtest.Assert(gconv.Int64(int64(1)), int64(1)) + gtest.Assert(gconv.Int64(int(0)), int64(0)) + gtest.Assert(gconv.Int64(int8(0)), int64(0)) + gtest.Assert(gconv.Int64(int16(0)), int64(0)) + gtest.Assert(gconv.Int64(int32(0)), int64(0)) + gtest.Assert(gconv.Int64(uint64(0)), int64(0)) + gtest.Assert(gconv.Int64(uint32(0)), int64(0)) + gtest.Assert(gconv.Int64(uint16(0)), int64(0)) + gtest.Assert(gconv.Int64(uint8(0)), int64(0)) + gtest.Assert(gconv.Int64(uint(0)), int64(0)) + gtest.Assert(gconv.Int64(float32(0)), int64(0)) + + gtest.AssertEQ(gconv.Int64(false), int64(0)) + gtest.AssertEQ(gconv.Int64(nil), int64(0)) + gtest.AssertEQ(gconv.Int64(0), int64(0)) + gtest.AssertEQ(gconv.Int64("0"), int64(0)) + gtest.AssertEQ(gconv.Int64(""), int64(0)) + gtest.AssertEQ(gconv.Int64("false"), int64(0)) + gtest.AssertEQ(gconv.Int64("off"), int64(0)) + gtest.AssertEQ(gconv.Int64([]byte{}), int64(0)) + gtest.AssertEQ(gconv.Int64([]string{}), int64(0)) + gtest.AssertEQ(gconv.Int64([2]int{1, 2}), int64(0)) + gtest.AssertEQ(gconv.Int64([]interface{}{}), int64(0)) + gtest.AssertEQ(gconv.Int64([]map[int]int{}), int64(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Int64(countryCapitalMap), int64(0)) + + gtest.AssertEQ(gconv.Int64("1"), int64(1)) + gtest.AssertEQ(gconv.Int64("on"), int64(0)) + gtest.AssertEQ(gconv.Int64(int64(1)), int64(1)) + gtest.AssertEQ(gconv.Int64(123.456), int64(123)) + gtest.AssertEQ(gconv.Int64(boolStruct{}), int64(0)) + gtest.AssertEQ(gconv.Int64(&boolStruct{}), int64(0)) + }) +} + +func Test_Uint_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.AssertEQ(gconv.Uint(i), uint(0)) + gtest.AssertEQ(gconv.Uint(false), uint(0)) + gtest.AssertEQ(gconv.Uint(nil), uint(0)) + gtest.Assert(gconv.Uint(nil), uint(0)) + gtest.AssertEQ(gconv.Uint(uint(0)), uint(0)) + gtest.AssertEQ(gconv.Uint("0"), uint(0)) + gtest.AssertEQ(gconv.Uint(""), uint(0)) + gtest.AssertEQ(gconv.Uint("false"), uint(0)) + gtest.AssertEQ(gconv.Uint("off"), uint(0)) + gtest.AssertEQ(gconv.Uint([]byte{}), uint(0)) + gtest.AssertEQ(gconv.Uint([]string{}), uint(0)) + gtest.AssertEQ(gconv.Uint([2]int{1, 2}), uint(0)) + gtest.AssertEQ(gconv.Uint([]interface{}{}), uint(0)) + gtest.AssertEQ(gconv.Uint([]map[int]int{}), uint(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Uint(countryCapitalMap), uint(0)) + + gtest.AssertEQ(gconv.Uint("1"), uint(1)) + gtest.AssertEQ(gconv.Uint("on"), uint(0)) + gtest.AssertEQ(gconv.Uint(1), uint(1)) + gtest.AssertEQ(gconv.Uint(123.456), uint(123)) + gtest.AssertEQ(gconv.Uint(boolStruct{}), uint(0)) + gtest.AssertEQ(gconv.Uint(&boolStruct{}), uint(0)) + }) +} + +func Test_Uint8_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Uint8(i), uint8(0)) + gtest.AssertEQ(gconv.Uint8(uint8(1)), uint8(1)) + gtest.AssertEQ(gconv.Uint8(false), uint8(0)) + gtest.AssertEQ(gconv.Uint8(nil), uint8(0)) + gtest.AssertEQ(gconv.Uint8(0), uint8(0)) + gtest.AssertEQ(gconv.Uint8("0"), uint8(0)) + gtest.AssertEQ(gconv.Uint8(""), uint8(0)) + gtest.AssertEQ(gconv.Uint8("false"), uint8(0)) + gtest.AssertEQ(gconv.Uint8("off"), uint8(0)) + gtest.AssertEQ(gconv.Uint8([]byte{}), uint8(0)) + gtest.AssertEQ(gconv.Uint8([]string{}), uint8(0)) + gtest.AssertEQ(gconv.Uint8([2]int{1, 2}), uint8(0)) + gtest.AssertEQ(gconv.Uint8([]interface{}{}), uint8(0)) + gtest.AssertEQ(gconv.Uint8([]map[int]int{}), uint8(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Uint8(countryCapitalMap), uint8(0)) + + gtest.AssertEQ(gconv.Uint8("1"), uint8(1)) + gtest.AssertEQ(gconv.Uint8("on"), uint8(0)) + gtest.AssertEQ(gconv.Uint8(int8(1)), uint8(1)) + gtest.AssertEQ(gconv.Uint8(123.456), uint8(123)) + gtest.AssertEQ(gconv.Uint8(boolStruct{}), uint8(0)) + gtest.AssertEQ(gconv.Uint8(&boolStruct{}), uint8(0)) + }) +} + +func Test_Uint16_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Uint16(i), uint16(0)) + gtest.AssertEQ(gconv.Uint16(uint16(1)), uint16(1)) + gtest.AssertEQ(gconv.Uint16(false), uint16(0)) + gtest.AssertEQ(gconv.Uint16(nil), uint16(0)) + gtest.AssertEQ(gconv.Uint16(0), uint16(0)) + gtest.AssertEQ(gconv.Uint16("0"), uint16(0)) + gtest.AssertEQ(gconv.Uint16(""), uint16(0)) + gtest.AssertEQ(gconv.Uint16("false"), uint16(0)) + gtest.AssertEQ(gconv.Uint16("off"), uint16(0)) + gtest.AssertEQ(gconv.Uint16([]byte{}), uint16(0)) + gtest.AssertEQ(gconv.Uint16([]string{}), uint16(0)) + gtest.AssertEQ(gconv.Uint16([2]int{1, 2}), uint16(0)) + gtest.AssertEQ(gconv.Uint16([]interface{}{}), uint16(0)) + gtest.AssertEQ(gconv.Uint16([]map[int]int{}), uint16(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Uint16(countryCapitalMap), uint16(0)) + + gtest.AssertEQ(gconv.Uint16("1"), uint16(1)) + gtest.AssertEQ(gconv.Uint16("on"), uint16(0)) + gtest.AssertEQ(gconv.Uint16(int16(1)), uint16(1)) + gtest.AssertEQ(gconv.Uint16(123.456), uint16(123)) + gtest.AssertEQ(gconv.Uint16(boolStruct{}), uint16(0)) + gtest.AssertEQ(gconv.Uint16(&boolStruct{}), uint16(0)) + }) +} + +func Test_Uint32_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Uint32(i), uint32(0)) + gtest.AssertEQ(gconv.Uint32(uint32(1)), uint32(1)) + gtest.AssertEQ(gconv.Uint32(false), uint32(0)) + gtest.AssertEQ(gconv.Uint32(nil), uint32(0)) + gtest.AssertEQ(gconv.Uint32(0), uint32(0)) + gtest.AssertEQ(gconv.Uint32("0"), uint32(0)) + gtest.AssertEQ(gconv.Uint32(""), uint32(0)) + gtest.AssertEQ(gconv.Uint32("false"), uint32(0)) + gtest.AssertEQ(gconv.Uint32("off"), uint32(0)) + gtest.AssertEQ(gconv.Uint32([]byte{}), uint32(0)) + gtest.AssertEQ(gconv.Uint32([]string{}), uint32(0)) + gtest.AssertEQ(gconv.Uint32([2]int{1, 2}), uint32(0)) + gtest.AssertEQ(gconv.Uint32([]interface{}{}), uint32(0)) + gtest.AssertEQ(gconv.Uint32([]map[int]int{}), uint32(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Uint32(countryCapitalMap), uint32(0)) + + gtest.AssertEQ(gconv.Uint32("1"), uint32(1)) + gtest.AssertEQ(gconv.Uint32("on"), uint32(0)) + gtest.AssertEQ(gconv.Uint32(int32(1)), uint32(1)) + gtest.AssertEQ(gconv.Uint32(123.456), uint32(123)) + gtest.AssertEQ(gconv.Uint32(boolStruct{}), uint32(0)) + gtest.AssertEQ(gconv.Uint32(&boolStruct{}), uint32(0)) + }) +} + +func Test_Uint64_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.AssertEQ(gconv.Uint64("0x00e"), uint64(14)) + gtest.Assert(gconv.Uint64("022"), uint64(18)) + + gtest.AssertEQ(gconv.Uint64(i), uint64(0)) + gtest.AssertEQ(gconv.Uint64(true), uint64(1)) + gtest.Assert(gconv.Uint64("1"), int64(1)) + gtest.Assert(gconv.Uint64("0"), uint64(0)) + gtest.Assert(gconv.Uint64("X"), uint64(0)) + gtest.Assert(gconv.Uint64("x"), uint64(0)) + gtest.Assert(gconv.Uint64(int64(1)), uint64(1)) + gtest.Assert(gconv.Uint64(int(0)), uint64(0)) + gtest.Assert(gconv.Uint64(int8(0)), uint64(0)) + gtest.Assert(gconv.Uint64(int16(0)), uint64(0)) + gtest.Assert(gconv.Uint64(int32(0)), uint64(0)) + gtest.Assert(gconv.Uint64(uint64(0)), uint64(0)) + gtest.Assert(gconv.Uint64(uint32(0)), uint64(0)) + gtest.Assert(gconv.Uint64(uint16(0)), uint64(0)) + gtest.Assert(gconv.Uint64(uint8(0)), uint64(0)) + gtest.Assert(gconv.Uint64(uint(0)), uint64(0)) + gtest.Assert(gconv.Uint64(float32(0)), uint64(0)) + + gtest.AssertEQ(gconv.Uint64(false), uint64(0)) + gtest.AssertEQ(gconv.Uint64(nil), uint64(0)) + gtest.AssertEQ(gconv.Uint64(0), uint64(0)) + gtest.AssertEQ(gconv.Uint64("0"), uint64(0)) + gtest.AssertEQ(gconv.Uint64(""), uint64(0)) + gtest.AssertEQ(gconv.Uint64("false"), uint64(0)) + gtest.AssertEQ(gconv.Uint64("off"), uint64(0)) + gtest.AssertEQ(gconv.Uint64([]byte{}), uint64(0)) + gtest.AssertEQ(gconv.Uint64([]string{}), uint64(0)) + gtest.AssertEQ(gconv.Uint64([2]int{1, 2}), uint64(0)) + gtest.AssertEQ(gconv.Uint64([]interface{}{}), uint64(0)) + gtest.AssertEQ(gconv.Uint64([]map[int]int{}), uint64(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Uint64(countryCapitalMap), uint64(0)) + + gtest.AssertEQ(gconv.Uint64("1"), uint64(1)) + gtest.AssertEQ(gconv.Uint64("on"), uint64(0)) + gtest.AssertEQ(gconv.Uint64(int64(1)), uint64(1)) + gtest.AssertEQ(gconv.Uint64(123.456), uint64(123)) + gtest.AssertEQ(gconv.Uint64(boolStruct{}), uint64(0)) + gtest.AssertEQ(gconv.Uint64(&boolStruct{}), uint64(0)) + }) +} + +func Test_Float32_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Float32(i), float32(0)) + gtest.AssertEQ(gconv.Float32(false), float32(0)) + gtest.AssertEQ(gconv.Float32(nil), float32(0)) + gtest.AssertEQ(gconv.Float32(0), float32(0)) + gtest.AssertEQ(gconv.Float32("0"), float32(0)) + gtest.AssertEQ(gconv.Float32(""), float32(0)) + gtest.AssertEQ(gconv.Float32("false"), float32(0)) + gtest.AssertEQ(gconv.Float32("off"), float32(0)) + gtest.AssertEQ(gconv.Float32([]byte{}), float32(0)) + gtest.AssertEQ(gconv.Float32([]string{}), float32(0)) + gtest.AssertEQ(gconv.Float32([2]int{1, 2}), float32(0)) + gtest.AssertEQ(gconv.Float32([]interface{}{}), float32(0)) + gtest.AssertEQ(gconv.Float32([]map[int]int{}), float32(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Float32(countryCapitalMap), float32(0)) + + gtest.AssertEQ(gconv.Float32("1"), float32(1)) + gtest.AssertEQ(gconv.Float32("on"), float32(0)) + gtest.AssertEQ(gconv.Float32(float32(1)), float32(1)) + gtest.AssertEQ(gconv.Float32(123.456), float32(123.456)) + gtest.AssertEQ(gconv.Float32(boolStruct{}), float32(0)) + gtest.AssertEQ(gconv.Float32(&boolStruct{}), float32(0)) + }) +} + +func Test_Float64_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.Assert(gconv.Float64(i), float64(0)) + gtest.AssertEQ(gconv.Float64(false), float64(0)) + gtest.AssertEQ(gconv.Float64(nil), float64(0)) + gtest.AssertEQ(gconv.Float64(0), float64(0)) + gtest.AssertEQ(gconv.Float64("0"), float64(0)) + gtest.AssertEQ(gconv.Float64(""), float64(0)) + gtest.AssertEQ(gconv.Float64("false"), float64(0)) + gtest.AssertEQ(gconv.Float64("off"), float64(0)) + gtest.AssertEQ(gconv.Float64([]byte{}), float64(0)) + gtest.AssertEQ(gconv.Float64([]string{}), float64(0)) + gtest.AssertEQ(gconv.Float64([2]int{1, 2}), float64(0)) + gtest.AssertEQ(gconv.Float64([]interface{}{}), float64(0)) + gtest.AssertEQ(gconv.Float64([]map[int]int{}), float64(0)) + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.Float64(countryCapitalMap), float64(0)) + + gtest.AssertEQ(gconv.Float64("1"), float64(1)) + gtest.AssertEQ(gconv.Float64("on"), float64(0)) + gtest.AssertEQ(gconv.Float64(float64(1)), float64(1)) + gtest.AssertEQ(gconv.Float64(123.456), float64(123.456)) + gtest.AssertEQ(gconv.Float64(boolStruct{}), float64(0)) + gtest.AssertEQ(gconv.Float64(&boolStruct{}), float64(0)) + }) +} + +func Test_String_All(t *testing.T) { + gtest.Case(t, func() { + var s []rune + gtest.AssertEQ(gconv.String(s), "") + var i interface{} = nil + gtest.AssertEQ(gconv.String(i), "") + gtest.AssertEQ(gconv.String("1"), "1") + gtest.AssertEQ(gconv.String("0"), string("0")) + gtest.Assert(gconv.String("X"), string("X")) + gtest.Assert(gconv.String("x"), string("x")) + gtest.Assert(gconv.String(int64(1)), uint64(1)) + gtest.Assert(gconv.String(int(0)), string("0")) + gtest.Assert(gconv.String(int8(0)), string("0")) + gtest.Assert(gconv.String(int16(0)), string("0")) + gtest.Assert(gconv.String(int32(0)), string("0")) + gtest.Assert(gconv.String(uint64(0)), string("0")) + gtest.Assert(gconv.String(uint32(0)), string("0")) + gtest.Assert(gconv.String(uint16(0)), string("0")) + gtest.Assert(gconv.String(uint8(0)), string("0")) + gtest.Assert(gconv.String(uint(0)), string("0")) + gtest.Assert(gconv.String(float32(0)), string("0")) + gtest.AssertEQ(gconv.String(true), "true") + gtest.AssertEQ(gconv.String(false), "false") + gtest.AssertEQ(gconv.String(nil), "") + gtest.AssertEQ(gconv.String(0), string("0")) + gtest.AssertEQ(gconv.String("0"), string("0")) + gtest.AssertEQ(gconv.String(""), "") + gtest.AssertEQ(gconv.String("false"), "false") + gtest.AssertEQ(gconv.String("off"), string("off")) + gtest.AssertEQ(gconv.String([]byte{}), "") + gtest.AssertEQ(gconv.String([]string{}), "[]") + gtest.AssertEQ(gconv.String([2]int{1, 2}), "[1,2]") + gtest.AssertEQ(gconv.String([]interface{}{}), "[]") + gtest.AssertEQ(gconv.String(map[int]int{}), "{}") + + var countryCapitalMap = make(map[string]string) + /* map插入key - value对,各个国家对应的首都 */ + countryCapitalMap["France"] = "巴黎" + countryCapitalMap["Italy"] = "罗马" + countryCapitalMap["Japan"] = "东京" + countryCapitalMap["India "] = "新德里" + gtest.AssertEQ(gconv.String(countryCapitalMap), `{"France":"巴黎","India ":"新德里","Italy":"罗马","Japan":"东京"}`) + gtest.AssertEQ(gconv.String(int64(1)), "1") + gtest.AssertEQ(gconv.String(123.456), "123.456") + gtest.AssertEQ(gconv.String(boolStruct{}), "{}") + gtest.AssertEQ(gconv.String(&boolStruct{}), "{}") + + var info apiString + info = new(S) + gtest.AssertEQ(gconv.String(info), "22222") + var errinfo apiError + errinfo = new(S1) + gtest.AssertEQ(gconv.String(errinfo), "22222") + }) +} + +func Test_Runes_All(t *testing.T) { + gtest.Case(t, func() { + gtest.AssertEQ(gconv.Runes("www"), []int32{119, 119, 119}) + var s []rune + gtest.AssertEQ(gconv.Runes(s), nil) + }) +} + +func Test_Rune_All(t *testing.T) { + gtest.Case(t, func() { + gtest.AssertEQ(gconv.Rune("www"), int32(0)) + gtest.AssertEQ(gconv.Rune(int32(0)), int32(0)) + var s []rune + gtest.AssertEQ(gconv.Rune(s), int32(0)) + }) +} + +func Test_Bytes_All(t *testing.T) { + gtest.Case(t, func() { + gtest.AssertEQ(gconv.Bytes(nil), nil) + gtest.AssertEQ(gconv.Bytes(int32(0)), []uint8{0, 0, 0, 0}) + gtest.AssertEQ(gconv.Bytes("s"), []uint8{115}) + gtest.AssertEQ(gconv.Bytes([]byte("s")), []uint8{115}) + }) +} + +func Test_Byte_All(t *testing.T) { + gtest.Case(t, func() { + gtest.AssertEQ(gconv.Byte(uint8(0)), uint8(0)) + gtest.AssertEQ(gconv.Byte("s"), uint8(0)) + gtest.AssertEQ(gconv.Byte([]byte("s")), uint8(0)) + }) +} + +func Test_Convert_All(t *testing.T) { + gtest.Case(t, func() { + var i interface{} = nil + gtest.AssertEQ(gconv.Convert(i, "string"), "") + gtest.AssertEQ(gconv.Convert("1", "string"), "1") + gtest.Assert(gconv.Convert(int64(1), "int64"), int64(1)) + gtest.Assert(gconv.Convert(int(0), "int"), int(0)) + gtest.Assert(gconv.Convert(int8(0), "int8"), int8(0)) + gtest.Assert(gconv.Convert(int16(0), "int16"), int16(0)) + gtest.Assert(gconv.Convert(int32(0), "int32"), int32(0)) + gtest.Assert(gconv.Convert(uint64(0), "uint64"), uint64(0)) + gtest.Assert(gconv.Convert(uint32(0), "uint32"), uint32(0)) + gtest.Assert(gconv.Convert(uint16(0), "uint16"), uint16(0)) + gtest.Assert(gconv.Convert(uint8(0), "uint8"), uint8(0)) + gtest.Assert(gconv.Convert(uint(0), "uint"), uint(0)) + gtest.Assert(gconv.Convert(float32(0), "float32"), float32(0)) + gtest.Assert(gconv.Convert(float64(0), "float64"), float64(0)) + gtest.AssertEQ(gconv.Convert(true, "bool"), true) + gtest.AssertEQ(gconv.Convert([]byte{}, "[]byte"), []uint8{}) + gtest.AssertEQ(gconv.Convert([]string{}, "[]string"), []string{}) + gtest.AssertEQ(gconv.Convert([2]int{1, 2}, "[]int"), []int{0}) + gtest.AssertEQ(gconv.Convert("1989-01-02", "Time", "Y-m-d"), gconv.Time("1989-01-02", "Y-m-d")) + gtest.AssertEQ(gconv.Convert(1989, "Time"), gconv.Time("2033-01-11 04:00:00 +0800 CST")) + gtest.AssertEQ(gconv.Convert(gtime.Now(), "gtime.Time", 1), nil) + gtest.AssertEQ(gconv.Convert(1989, "gtime.Time"), gtime.Time{gconv.Time("2033-01-11 04:00:00 +0800 CST")}) + gtest.AssertEQ(gconv.Convert(gtime.Now(), "*gtime.Time", 1), nil) + gtest.AssertEQ(gconv.Convert(gtime.Now(), "GTime", 1), nil) + gtest.AssertEQ(gconv.Convert(1989, "*gtime.Time"), gconv.GTime(1989)) + gtest.AssertEQ(gconv.Convert(1989, "Duration"), time.Duration(int64(1989))) + gtest.AssertEQ(gconv.Convert("1989", "Duration"), time.Duration(int64(1989))) + gtest.AssertEQ(gconv.Convert("1989", ""), "1989") + }) +} + +func Test_Time_All(t *testing.T) { + gtest.Case(t, func() { + gtest.AssertEQ(gconv.Duration(""), time.Duration(int64(0))) + gtest.AssertEQ(gconv.GTime(""), gtime.New()) + }) +} + +func Test_Slice_All(t *testing.T) { + gtest.Case(t, func() { + value := 123.456 + gtest.AssertEQ(gconv.Ints(value), []int{123}) + gtest.AssertEQ(gconv.Ints(nil), nil) + gtest.AssertEQ(gconv.Ints([]string{"1", "2"}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]int{}), []int{}) + gtest.AssertEQ(gconv.Ints([]int8{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]int16{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]int32{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]int64{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]uint{1}), []int{1}) + gtest.AssertEQ(gconv.Ints([]uint8{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]uint16{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]uint32{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]uint64{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]bool{true}), []int{1}) + gtest.AssertEQ(gconv.Ints([]float32{1, 2}), []int{1, 2}) + gtest.AssertEQ(gconv.Ints([]float64{1, 2}), []int{1, 2}) + var inter []interface{} = make([]interface{}, 2) + gtest.AssertEQ(gconv.Ints(inter), []int{0, 0}) + + gtest.AssertEQ(gconv.Strings(value), []string{"123.456"}) + gtest.AssertEQ(gconv.Strings(nil), nil) + gtest.AssertEQ(gconv.Strings([]string{"1", "2"}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]int{1}), []string{"1"}) + gtest.AssertEQ(gconv.Strings([]int8{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]int16{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]int32{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]int64{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]uint{1}), []string{"1"}) + gtest.AssertEQ(gconv.Strings([]uint8{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]uint16{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]uint32{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]uint64{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]bool{true}), []string{"true"}) + gtest.AssertEQ(gconv.Strings([]float32{1, 2}), []string{"1", "2"}) + gtest.AssertEQ(gconv.Strings([]float64{1, 2}), []string{"1", "2"}) + var strer []interface{} = make([]interface{}, 2) + gtest.AssertEQ(gconv.Strings(strer), []string{" "}) + + gtest.AssertEQ(gconv.Floats(value), []float64{123.456}) + gtest.AssertEQ(gconv.Floats(nil), nil) + gtest.AssertEQ(gconv.Floats([]string{"1", "2"}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]int{1}), []float64{1}) + gtest.AssertEQ(gconv.Floats([]int8{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]int16{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]int32{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]int64{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]uint{1}), []float64{1}) + gtest.AssertEQ(gconv.Floats([]uint8{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]uint16{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]uint32{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]uint64{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]bool{true}), []float64{0}) + gtest.AssertEQ(gconv.Floats([]float32{1, 2}), []float64{1, 2}) + gtest.AssertEQ(gconv.Floats([]float64{1, 2}), []float64{1, 2}) + var floer []interface{} = make([]interface{}, 2) + gtest.AssertEQ(gconv.Floats(floer), []float64{0, 0}) + + gtest.AssertEQ(gconv.Interfaces(value), []interface{}{123.456}) + gtest.AssertEQ(gconv.Interfaces(nil), nil) + gtest.AssertEQ(gconv.Interfaces([]interface{}{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]string{"1"}), []interface{}{"1"}) + gtest.AssertEQ(gconv.Interfaces([]int{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]int8{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]int16{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]int32{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]int64{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]uint{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]uint8{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]uint16{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]uint32{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]uint64{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]bool{true}), []interface{}{true}) + gtest.AssertEQ(gconv.Interfaces([]float32{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([]float64{1}), []interface{}{1}) + gtest.AssertEQ(gconv.Interfaces([1]int{1}), []interface{}{1}) + + type interSlice []int + slices := interSlice{1} + gtest.AssertEQ(gconv.Interfaces(slices), []interface{}{1}) + + gtest.AssertEQ(gconv.Maps(nil), nil) + gtest.AssertEQ(gconv.Maps([]map[string]interface{}{{"a": "1"}}), []map[string]interface{}{{"a": "1"}}) + gtest.AssertEQ(gconv.Maps(1223), []map[string]interface{}{{}}) + gtest.AssertEQ(gconv.Maps([]int{}), nil) + }) +} + +// 私有属性不会进行转换 +func Test_Slice_PrivateAttribute_All(t *testing.T) { + type User struct { + Id int + name string + Ad []interface{} + } + gtest.Case(t, func() { + user := &User{1, "john", []interface{}{2}} + gtest.Assert(gconv.Interfaces(user), g.Slice{1, []interface{}{2}}) + }) +} + +func Test_Map_Basic_All(t *testing.T) { + gtest.Case(t, func() { + m1 := map[string]string{ + "k": "v", + } + m2 := map[int]string{ + 3: "v", + } + m3 := map[float64]float32{ + 1.22: 3.1, + } + gtest.Assert(gconv.Map(m1), g.Map{ + "k": "v", + }) + gtest.Assert(gconv.Map(m2), g.Map{ + "3": "v", + }) + gtest.Assert(gconv.Map(m3), g.Map{ + "1.22": "3.1", + }) + gtest.AssertEQ(gconv.Map(nil), nil) + gtest.AssertEQ(gconv.Map(map[string]interface{}{"a": 1}), map[string]interface{}{"a": 1}) + gtest.AssertEQ(gconv.Map(map[int]interface{}{1: 1}), map[string]interface{}{"1": 1}) + gtest.AssertEQ(gconv.Map(map[uint]interface{}{1: 1}), map[string]interface{}{"1": 1}) + gtest.AssertEQ(gconv.Map(map[uint]string{1: "1"}), map[string]interface{}{"1": "1"}) + + gtest.AssertEQ(gconv.Map(map[interface{}]interface{}{"a": 1}), map[interface{}]interface{}{"a": 1}) + gtest.AssertEQ(gconv.Map(map[interface{}]string{"a": "1"}), map[interface{}]string{"a": "1"}) + gtest.AssertEQ(gconv.Map(map[interface{}]int{"a": 1}), map[interface{}]int{"a": 1}) + gtest.AssertEQ(gconv.Map(map[interface{}]uint{"a": 1}), map[interface{}]uint{"a": 1}) + gtest.AssertEQ(gconv.Map(map[interface{}]float32{"a": 1}), map[interface{}]float32{"a": 1}) + gtest.AssertEQ(gconv.Map(map[interface{}]float64{"a": 1}), map[interface{}]float64{"a": 1}) + + gtest.AssertEQ(gconv.Map(map[string]bool{"a": true}), map[string]interface{}{"a": true}) + gtest.AssertEQ(gconv.Map(map[string]int{"a": 1}), map[string]interface{}{"a": 1}) + gtest.AssertEQ(gconv.Map(map[string]uint{"a": 1}), map[string]interface{}{"a": 1}) + gtest.AssertEQ(gconv.Map(map[string]float32{"a": 1}), map[string]interface{}{"a": 1}) + gtest.AssertEQ(gconv.Map(map[string]float64{"a": 1}), map[string]interface{}{"a": 1}) + + }) +} + +func Test_Map_StructWithGconvTag_All(t *testing.T) { + gtest.Case(t, func() { + type User struct { + Uid int + Name string + SiteUrl string `gconv:"-"` + NickName string `gconv:"nickname,omitempty"` + Pass1 string `gconv:"password1"` + Pass2 string `gconv:"password2"` + Ss []string `gconv:"ss"` + } + user1 := User{ + Uid: 100, + Name: "john", + SiteUrl: "https://goframe.org", + Pass1: "123", + Pass2: "456", + Ss: []string{"sss", "2222"}, + } + user2 := &user1 + map1 := gconv.Map(user1) + map2 := gconv.Map(user2) + gtest.Assert(map1["Uid"], 100) + gtest.Assert(map1["Name"], "john") + gtest.Assert(map1["SiteUrl"], nil) + gtest.Assert(map1["NickName"], nil) + gtest.Assert(map1["nickname"], nil) + gtest.Assert(map1["password1"], "123") + gtest.Assert(map1["password2"], "456") + gtest.Assert(map2["Uid"], 100) + gtest.Assert(map2["Name"], "john") + gtest.Assert(map2["SiteUrl"], nil) + gtest.Assert(map2["NickName"], nil) + gtest.Assert(map2["nickname"], nil) + gtest.Assert(map2["password1"], "123") + gtest.Assert(map2["password2"], "456") + }) +} + +func Test_Map_StructWithJsonTag_All(t *testing.T) { + gtest.Case(t, func() { + type User struct { + Uid int + Name string + SiteUrl string `json:"-"` + NickName string `json:"nickname, omitempty"` + Pass1 string `json:"password1,newpassword"` + Pass2 string `json:"password2"` + Ss []string `json:"omitempty"` + ssb, ssa string + } + user1 := User{ + Uid: 100, + Name: "john", + SiteUrl: "https://goframe.org", + Pass1: "123", + Pass2: "456", + Ss: []string{"sss", "2222"}, + ssb: "11", + ssa: "222", + } + user3 := User{ + Uid: 100, + Name: "john", + NickName: "SSS", + SiteUrl: "https://goframe.org", + Pass1: "123", + Pass2: "456", + Ss: []string{"sss", "2222"}, + ssb: "11", + ssa: "222", + } + user2 := &user1 + _ = gconv.Map(user1, "Ss") + map1 := gconv.Map(user1, "json", "json2") + map2 := gconv.Map(user2) + map3 := gconv.Map(user3) + gtest.Assert(map1["Uid"], 100) + gtest.Assert(map1["Name"], "john") + gtest.Assert(map1["SiteUrl"], nil) + gtest.Assert(map1["NickName"], nil) + gtest.Assert(map1["nickname"], nil) + gtest.Assert(map1["password1"], "123") + gtest.Assert(map1["password2"], "456") + gtest.Assert(map2["Uid"], 100) + gtest.Assert(map2["Name"], "john") + gtest.Assert(map2["SiteUrl"], nil) + gtest.Assert(map2["NickName"], nil) + gtest.Assert(map2["nickname"], nil) + gtest.Assert(map2["password1"], "123") + gtest.Assert(map2["password2"], "456") + gtest.Assert(map3["NickName"], nil) + }) +} + +func Test_Map_PrivateAttribute_All(t *testing.T) { + type User struct { + Id int + name string + } + gtest.Case(t, func() { + user := &User{1, "john"} + gtest.Assert(gconv.Map(user), g.Map{"Id": 1}) + }) +} + +func Test_Map_StructInherit_All(t *testing.T) { + gtest.Case(t, func() { + type Ids struct { + Id int `json:"id"` + Uid int `json:"uid"` + } + type Base struct { + Ids + CreateTime string `json:"create_time"` + } + type User struct { + Base + Passport string `json:"passport"` + Password string `json:"password"` + Nickname string `json:"nickname"` + S *string `json:"nickname2"` + } + + user := new(User) + user.Id = 100 + user.Nickname = "john" + user.CreateTime = "2019" + var s = "s" + user.S = &s + + m := gconv.MapDeep(user) + gtest.Assert(m["id"], user.Id) + gtest.Assert(m["nickname"], user.Nickname) + gtest.Assert(m["create_time"], user.CreateTime) + gtest.Assert(m["nickname2"], user.S) + }) +} + +func Test_Struct_Basic1_All(t *testing.T) { + gtest.Case(t, func() { + + type Score struct { + Name int + Result string + } + + type Score2 struct { + Name int + Result string + } + + type User struct { + Uid int + Name string + Site_Url string + NickName string + Pass1 string `gconv:"password1"` + Pass2 string `gconv:"password2"` + As *Score + Ass Score + Assb []interface{} + } + // 使用默认映射规则绑定属性值到对象 + user := new(User) + params1 := g.Map{ + "uid": 1, + "Name": "john", + "siteurl": "https://goframe.org", + "nick_name": "johng", + "PASS1": "123", + "PASS2": "456", + "As": g.Map{"Name": 1, "Result": "22222"}, + "Ass": &Score{11, "11"}, + "Assb": []string{"wwww"}, + } + _ = gconv.Struct(nil, user) + _ = gconv.Struct(params1, nil) + _ = gconv.Struct([]interface{}{nil}, user) + _ = gconv.Struct(user, []interface{}{nil}) + + var a = []interface{}{nil} + ab := &a + _ = gconv.Struct(params1, *ab) + var pi *int = nil + _ = gconv.Struct(params1, pi) + + _ = gconv.Struct(params1, user) + _ = gconv.Struct(params1, user, map[string]string{"uid": "Names"}) + _ = gconv.Struct(params1, user, map[string]string{"uid": "as"}) + + // 使用struct tag映射绑定属性值到对象 + user = new(User) + params2 := g.Map{ + "uid": 2, + "name": "smith", + "site-url": "https://goframe.org", + "nick name": "johng", + "password1": "111", + "password2": "222", + } + if err := gconv.Struct(params2, user); err != nil { + gtest.Error(err) + } + gtest.Assert(user, &User{ + Uid: 2, + Name: "smith", + Site_Url: "https://goframe.org", + NickName: "johng", + Pass1: "111", + Pass2: "222", + }) + }) +} + +// 使用默认映射规则绑定属性值到对象 +func Test_Struct_Basic2_All(t *testing.T) { + gtest.Case(t, func() { + type User struct { + Uid int + Name string + SiteUrl string + Pass1 string + Pass2 string + } + user := new(User) + params := g.Map{ + "uid": 1, + "Name": "john", + "site_url": "https://goframe.org", + "PASS1": "123", + "PASS2": "456", + } + if err := gconv.Struct(params, user); err != nil { + gtest.Error(err) + } + gtest.Assert(user, &User{ + Uid: 1, + Name: "john", + SiteUrl: "https://goframe.org", + Pass1: "123", + Pass2: "456", + }) + }) +} + +// 带有指针的基础类型属性 +func Test_Struct_Basic3_All(t *testing.T) { + gtest.Case(t, func() { + type User struct { + Uid int + Name *string + } + user := new(User) + params := g.Map{ + "uid": 1, + "Name": "john", + } + if err := gconv.Struct(params, user); err != nil { + gtest.Error(err) + } + gtest.Assert(user.Uid, 1) + gtest.Assert(*user.Name, "john") + }) +} + +// slice类型属性的赋值 +func Test_Struct_Attr_Slice_All(t *testing.T) { + gtest.Case(t, func() { + type User struct { + Scores []int + } + scores := []interface{}{99, 100, 60, 140} + user := new(User) + if err := gconv.Struct(g.Map{"Scores": scores}, user); err != nil { + gtest.Error(err) + } else { + gtest.Assert(user, &User{ + Scores: []int{99, 100, 60, 140}, + }) + } + }) +} + +// 属性为struct对象 +func Test_Struct_Attr_Struct_All(t *testing.T) { + gtest.Case(t, func() { + type Score struct { + Name string + Result int + } + type User struct { + Scores Score + } + + user := new(User) + scores := map[string]interface{}{ + "Scores": map[string]interface{}{ + "Name": "john", + "Result": 100, + }, + } + + // 嵌套struct转换 + if err := gconv.Struct(scores, user); err != nil { + gtest.Error(err) + } else { + gtest.Assert(user, &User{ + Scores: Score{ + Name: "john", + Result: 100, + }, + }) + } + }) +} + +// 属性为struct对象指针 +func Test_Struct_Attr_Struct_Ptr_All(t *testing.T) { + gtest.Case(t, func() { + type Score struct { + Name string + Result int + } + type User struct { + Scores *Score + } + + user := new(User) + scores := map[string]interface{}{ + "Scores": map[string]interface{}{ + "Name": "john", + "Result": 100, + }, + } + + // 嵌套struct转换 + if err := gconv.Struct(scores, user); err != nil { + gtest.Error(err) + } else { + gtest.Assert(user.Scores, &Score{ + Name: "john", + Result: 100, + }) + } + }) +} + +// 属性为struct对象slice +func Test_Struct_Attr_Struct_Slice1_All(t *testing.T) { + gtest.Case(t, func() { + type Score struct { + Name string + Result int + } + type User struct { + Scores []Score + } + + user := new(User) + scores := map[string]interface{}{ + "Scores": map[string]interface{}{ + "Name": "john", + "Result": 100, + }, + } + + // 嵌套struct转换,属性为slice类型,数值为map类型 + if err := gconv.Struct(scores, user); err != nil { + gtest.Error(err) + } else { + gtest.Assert(user.Scores, []Score{ + { + Name: "john", + Result: 100, + }, + }) + } + }) +} + +// 属性为struct对象slice +func Test_Struct_Attr_Struct_Slice2_All(t *testing.T) { + gtest.Case(t, func() { + type Score struct { + Name string + Result int + } + type User struct { + Scores []Score + } + + user := new(User) + scores := map[string]interface{}{ + "Scores": []interface{}{ + map[string]interface{}{ + "Name": "john", + "Result": 100, + }, + map[string]interface{}{ + "Name": "smith", + "Result": 60, + }, + }, + } + + // 嵌套struct转换,属性为slice类型,数值为slice map类型 + if err := gconv.Struct(scores, user); err != nil { + gtest.Error(err) + } else { + gtest.Assert(user.Scores, []Score{ + { + Name: "john", + Result: 100, + }, + { + Name: "smith", + Result: 60, + }, + }) + } + }) +} + +// 属性为struct对象slice ptr +func Test_Struct_Attr_Struct_Slice_Ptr_All(t *testing.T) { + gtest.Case(t, func() { + type Score struct { + Name string + Result int + } + type User struct { + Scores []*Score + } + + user := new(User) + scores := map[string]interface{}{ + "Scores": []interface{}{ + map[string]interface{}{ + "Name": "john", + "Result": 100, + }, + map[string]interface{}{ + "Name": "smith", + "Result": 60, + }, + }, + } + + // 嵌套struct转换,属性为slice类型,数值为slice map类型 + if err := gconv.Struct(scores, user); err != nil { + gtest.Error(err) + } else { + gtest.Assert(len(user.Scores), 2) + gtest.Assert(user.Scores[0], &Score{ + Name: "john", + Result: 100, + }) + gtest.Assert(user.Scores[1], &Score{ + Name: "smith", + Result: 60, + }) + } + }) +} + +func Test_Struct_PrivateAttribute_All(t *testing.T) { + type User struct { + Id int + name string + } + gtest.Case(t, func() { + user := new(User) + err := gconv.Struct(g.Map{"id": 1, "name": "john"}, user) + gtest.Assert(err, nil) + gtest.Assert(user.Id, 1) + gtest.Assert(user.name, "") + }) +} + +func Test_Struct_Deep_All(t *testing.T) { + gtest.Case(t, func() { + type Ids struct { + Id int `json:"id"` + Uid int `json:"uid"` + } + type Base struct { + Ids + CreateTime string `json:"create_time"` + } + type User struct { + Base + Passport string `json:"passport"` + Password string `json:"password"` + Nickname string `json:"nickname"` + } + data := g.Map{ + "id": 100, + "uid": 101, + "passport": "t1", + "password": "123456", + "nickname": "T1", + "create_time": "2019", + } + user := new(User) + gconv.StructDeep(data, user) + gtest.Assert(user.Id, 100) + gtest.Assert(user.Uid, 101) + gtest.Assert(user.Nickname, "T1") + gtest.Assert(user.CreateTime, "2019") + }) +} + +func Test_Struct_Time_All(t *testing.T) { + gtest.Case(t, func() { + type User struct { + CreateTime time.Time + } + now := time.Now() + user := new(User) + gconv.Struct(g.Map{ + "create_time": now, + }, user) + gtest.Assert(user.CreateTime.UTC().String(), now.UTC().String()) + }) + + gtest.Case(t, func() { + type User struct { + CreateTime *time.Time + } + now := time.Now() + user := new(User) + gconv.Struct(g.Map{ + "create_time": &now, + }, user) + gtest.Assert(user.CreateTime.UTC().String(), now.UTC().String()) + }) + + gtest.Case(t, func() { + type User struct { + CreateTime *gtime.Time + } + now := time.Now() + user := new(User) + gconv.Struct(g.Map{ + "create_time": &now, + }, user) + gtest.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String()) + }) + + gtest.Case(t, func() { + type User struct { + CreateTime gtime.Time + } + now := time.Now() + user := new(User) + gconv.Struct(g.Map{ + "create_time": &now, + }, user) + gtest.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String()) + }) + + gtest.Case(t, func() { + type User struct { + CreateTime gtime.Time + } + now := time.Now() + user := new(User) + gconv.Struct(g.Map{ + "create_time": now, + }, user) + gtest.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String()) + }) +} diff --git a/g/util/gutil/gutil_comparator_z_unit_test.go b/g/util/gutil/gutil_comparator_z_unit_test.go new file mode 100755 index 000000000..82b556a68 --- /dev/null +++ b/g/util/gutil/gutil_comparator_z_unit_test.go @@ -0,0 +1,156 @@ +package gutil_test + +import ( + "testing" + + "github.com/gogf/gf/g/test/gtest" + "github.com/gogf/gf/g/util/gutil" +) + +func Test_ComparatorString(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorString(1, 1), 0) + gtest.Assert(gutil.ComparatorString(1, 2), -1) + gtest.Assert(gutil.ComparatorString(2, 1), 1) + }) +} + +func Test_ComparatorInt(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorInt(1, 1), 0) + gtest.Assert(gutil.ComparatorInt(1, 2), -1) + gtest.Assert(gutil.ComparatorInt(2, 1), 1) + }) +} + +func Test_ComparatorInt8(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorInt8(1, 1), 0) + gtest.Assert(gutil.ComparatorInt8(1, 2), -1) + gtest.Assert(gutil.ComparatorInt8(2, 1), 1) + }) +} + +func Test_ComparatorInt16(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorInt16(1, 1), 0) + gtest.Assert(gutil.ComparatorInt16(1, 2), -1) + gtest.Assert(gutil.ComparatorInt16(2, 1), 1) + }) +} + +func Test_ComparatorInt32(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorInt32(1, 1), 0) + gtest.Assert(gutil.ComparatorInt32(1, 2), -1) + gtest.Assert(gutil.ComparatorInt32(2, 1), 1) + }) +} + +func Test_ComparatorInt64(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorInt64(1, 1), 0) + gtest.Assert(gutil.ComparatorInt64(1, 2), -1) + gtest.Assert(gutil.ComparatorInt64(2, 1), 1) + }) +} + +func Test_ComparatorUint(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorUint(1, 1), 0) + gtest.Assert(gutil.ComparatorUint(1, 2), -1) + gtest.Assert(gutil.ComparatorUint(2, 1), 1) + }) +} + +func Test_ComparatorUint8(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorUint8(1, 1), 0) + gtest.Assert(gutil.ComparatorUint8(2, 6), 252) + gtest.Assert(gutil.ComparatorUint8(2, 1), 1) + }) +} + +func Test_ComparatorUint16(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorUint16(1, 1), 0) + gtest.Assert(gutil.ComparatorUint16(1, 2), 65535) + gtest.Assert(gutil.ComparatorUint16(2, 1), 1) + }) +} + +func Test_ComparatorUint32(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorUint32(1, 1), 0) + gtest.Assert(gutil.ComparatorUint32(-1000, 2147483640), 2147482656) + gtest.Assert(gutil.ComparatorUint32(2, 1), 1) + }) +} + +func Test_ComparatorUint64(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorUint64(1, 1), 0) + gtest.Assert(gutil.ComparatorUint64(1, 2), -1) + gtest.Assert(gutil.ComparatorUint64(2, 1), 1) + }) +} + +func Test_ComparatorFloat32(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorFloat32(1, 1), 0) + gtest.Assert(gutil.ComparatorFloat32(1, 2), -1) + gtest.Assert(gutil.ComparatorFloat32(2, 1), 1) + }) +} + +func Test_ComparatorFloat64(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorFloat64(1, 1), 0) + gtest.Assert(gutil.ComparatorFloat64(1, 2), -1) + gtest.Assert(gutil.ComparatorFloat64(2, 1), 1) + }) +} + +func Test_ComparatorByte(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorByte(1, 1), 0) + gtest.Assert(gutil.ComparatorByte(1, 2), 255) + gtest.Assert(gutil.ComparatorByte(2, 1), 1) + }) +} + +func Test_ComparatorRune(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.ComparatorRune(1, 1), 0) + gtest.Assert(gutil.ComparatorRune(1, 2), -1) + gtest.Assert(gutil.ComparatorRune(2, 1), 1) + }) +} + +func Test_ComparatorTime(t *testing.T) { + gtest.Case(t, func() { + j := gutil.ComparatorTime("2019-06-14", "2019-06-14") + gtest.Assert(j, 0) + + k := gutil.ComparatorTime("2019-06-15", "2019-06-14") + gtest.Assert(k, 1) + + l := gutil.ComparatorTime("2019-06-13", "2019-06-14") + gtest.Assert(l, -1) + }) +} diff --git a/g/util/gutil/gutil_z_unit_test.go b/g/util/gutil/gutil_z_unit_test.go new file mode 100755 index 000000000..cf52edc2a --- /dev/null +++ b/g/util/gutil/gutil_z_unit_test.go @@ -0,0 +1,66 @@ +package gutil_test + +import ( + "testing" + + "github.com/gogf/gf/g/test/gtest" + "github.com/gogf/gf/g/util/gutil" +) + +func Test_Dump(t *testing.T) { + gtest.Case(t, func() { + gutil.Dump(map[int]int{ + 100: 100, + }) + }) + + gtest.Case(t, func() { + gutil.Dump(map[string]interface{}{"": func() {}}) + }) + + gtest.Case(t, func() { + gutil.Dump([]byte("gutil Dump test")) + }) +} + +func Test_PrintBacktrace(t *testing.T) { + gtest.Case(t, func() { + gutil.PrintBacktrace() + }) +} + +func Test_TryCatch(t *testing.T) { + + gtest.Case(t, func() { + gutil.TryCatch(func() { + panic("gutil TryCatch test") + }) + }) + + gtest.Case(t, func() { + gutil.TryCatch(func() { + panic("gutil TryCatch test") + + }, func(err interface{}) { + gtest.Assert(err, "gutil TryCatch test") + }) + }) +} + +func Test_IsEmpty(t *testing.T) { + + gtest.Case(t, func() { + gtest.Assert(gutil.IsEmpty(1), false) + }) +} + +func Test_Throw(t *testing.T) { + + gtest.Case(t, func() { + defer func() { + gtest.Assert(recover(), "gutil Throw test") + }() + + gutil.Throw("gutil Throw test") + }) +} diff --git a/g/util/gvalid/gvalid_check_struct.go b/g/util/gvalid/gvalid_check_struct.go index e2750ad3d..cc025d722 100644 --- a/g/util/gvalid/gvalid_check_struct.go +++ b/g/util/gvalid/gvalid_check_struct.go @@ -69,7 +69,12 @@ func CheckStruct(object interface{}, rules interface{}, msgs ...CustomMsg) *Erro continue } params[fieldName] = field.Value() - if tag := field.Tag("gvalid"); tag != "" { + // 同时支持valid和gvalid标签,优先使用valid + tag := field.Tag("valid") + if tag == "" { + tag = field.Tag("gvalid") + } + if tag != "" { // sequence tag == struct tag, 这里的name为别名 name, rule, msg := parseSequenceTag(tag) if len(name) == 0 { diff --git a/g/util/gvalid/gvalid_unit_checkstruct_test.go b/g/util/gvalid/gvalid_unit_checkstruct_test.go index 7094a9b82..40e3178f0 100644 --- a/g/util/gvalid/gvalid_unit_checkstruct_test.go +++ b/g/util/gvalid/gvalid_unit_checkstruct_test.go @@ -7,9 +7,10 @@ package gvalid_test import ( + "testing" + "github.com/gogf/gf/g/test/gtest" "github.com/gogf/gf/g/util/gvalid" - "testing" ) func Test_CheckStruct(t *testing.T) { @@ -51,6 +52,7 @@ func Test_CheckStruct(t *testing.T) { gtest.Assert(err.Maps()["password"]["required"], "登录密码不能为空") }) + // gvalid tag gtest.Case(t, func() { type User struct { Id int `gvalid:"uid@required|min:10#|ID不能为空"` @@ -69,4 +71,22 @@ func Test_CheckStruct(t *testing.T) { gtest.Assert(err.Maps()["uid"]["min"], "ID不能为空") }) + // valid tag + gtest.Case(t, func() { + type User struct { + Id int `valid:"uid@required|min:10#|ID不能为空"` + Age int `valid:"age@required#年龄不能为空"` + Username string `json:"username" gvalid:"username@required#用户名不能为空"` + Password string `json:"password" gvalid:"password@required#登录密码不能为空"` + } + user := &User{ + Id: 1, + Username: "john", + Password: "123456", + } + err := gvalid.CheckStruct(user, nil) + gtest.AssertNE(err, nil) + gtest.Assert(len(err.Maps()), 1) + gtest.Assert(err.Maps()["uid"]["min"], "ID不能为空") + }) } diff --git a/geg/database/orm/mssql/gdb_sqlserver.go b/geg/database/gdb/mssql/gdb_sqlserver.go similarity index 100% rename from geg/database/orm/mssql/gdb_sqlserver.go rename to geg/database/gdb/mssql/gdb_sqlserver.go diff --git a/geg/database/orm/mysql/config.toml b/geg/database/gdb/mysql/config.toml similarity index 100% rename from geg/database/orm/mysql/config.toml rename to geg/database/gdb/mysql/config.toml diff --git a/geg/database/orm/mysql/gdb.go b/geg/database/gdb/mysql/gdb.go similarity index 100% rename from geg/database/orm/mysql/gdb.go rename to geg/database/gdb/mysql/gdb.go diff --git a/geg/database/orm/mysql/gdb_binary.go b/geg/database/gdb/mysql/gdb_binary.go similarity index 100% rename from geg/database/orm/mysql/gdb_binary.go rename to geg/database/gdb/mysql/gdb_binary.go diff --git a/geg/database/orm/mysql/gdb_cache.go b/geg/database/gdb/mysql/gdb_cache.go similarity index 100% rename from geg/database/orm/mysql/gdb_cache.go rename to geg/database/gdb/mysql/gdb_cache.go diff --git a/geg/database/orm/mysql/gdb_config.go b/geg/database/gdb/mysql/gdb_config.go similarity index 100% rename from geg/database/orm/mysql/gdb_config.go rename to geg/database/gdb/mysql/gdb_config.go diff --git a/geg/database/orm/mysql/gdb_datetime.go b/geg/database/gdb/mysql/gdb_datetime.go similarity index 100% rename from geg/database/orm/mysql/gdb_datetime.go rename to geg/database/gdb/mysql/gdb_datetime.go diff --git a/geg/database/orm/mysql/gdb_debug.go b/geg/database/gdb/mysql/gdb_debug.go similarity index 94% rename from geg/database/orm/mysql/gdb_debug.go rename to geg/database/gdb/mysql/gdb_debug.go index f171f68a4..8354514e2 100644 --- a/geg/database/orm/mysql/gdb_debug.go +++ b/geg/database/gdb/mysql/gdb_debug.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "github.com/gogf/gf/g" "github.com/gogf/gf/g/database/gdb" "github.com/gogf/gf/g/os/glog" @@ -22,8 +23,11 @@ func main() { if err != nil { panic(err) } - glog.SetPath("/tmp") db.SetDebug(true) + db.Table("user").Limit(2).Delete() + return + glog.SetPath("/tmp") + // 执行3条SQL查询 for i := 1; i <= 3; i++ { db.Table("user").Where("uid=?", i).One() diff --git a/geg/database/orm/mysql/gdb_insert.go b/geg/database/gdb/mysql/gdb_insert.go similarity index 100% rename from geg/database/orm/mysql/gdb_insert.go rename to geg/database/gdb/mysql/gdb_insert.go diff --git a/geg/database/orm/mysql/gdb_json_xml.go b/geg/database/gdb/mysql/gdb_json_xml.go similarity index 100% rename from geg/database/orm/mysql/gdb_json_xml.go rename to geg/database/gdb/mysql/gdb_json_xml.go diff --git a/geg/database/orm/mysql/gdb_pool.go b/geg/database/gdb/mysql/gdb_pool.go similarity index 100% rename from geg/database/orm/mysql/gdb_pool.go rename to geg/database/gdb/mysql/gdb_pool.go diff --git a/geg/database/orm/mysql/gdb_update_union.go b/geg/database/gdb/mysql/gdb_update_union.go similarity index 100% rename from geg/database/orm/mysql/gdb_update_union.go rename to geg/database/gdb/mysql/gdb_update_union.go diff --git a/geg/database/orm/mysql/gdb_value.go b/geg/database/gdb/mysql/gdb_value.go similarity index 100% rename from geg/database/orm/mysql/gdb_value.go rename to geg/database/gdb/mysql/gdb_value.go diff --git a/geg/database/orm/oracle/gdb.go b/geg/database/gdb/oracle/gdb.go similarity index 100% rename from geg/database/orm/oracle/gdb.go rename to geg/database/gdb/oracle/gdb.go diff --git a/geg/database/orm/sqlite/sqlite.go b/geg/database/gdb/sqlite/sqlite.go similarity index 100% rename from geg/database/orm/sqlite/sqlite.go rename to geg/database/gdb/sqlite/sqlite.go diff --git a/geg/database/redis/config.toml b/geg/database/gredis/config.toml similarity index 100% rename from geg/database/redis/config.toml rename to geg/database/gredis/config.toml diff --git a/geg/database/redis/gredis.go b/geg/database/gredis/gredis.go similarity index 100% rename from geg/database/redis/gredis.go rename to geg/database/gredis/gredis.go diff --git a/geg/database/redis/gredis2.go b/geg/database/gredis/gredis2.go similarity index 100% rename from geg/database/redis/gredis2.go rename to geg/database/gredis/gredis2.go diff --git a/geg/database/redis/gredis_conn_do.go b/geg/database/gredis/gredis_conn_do.go similarity index 100% rename from geg/database/redis/gredis_conn_do.go rename to geg/database/gredis/gredis_conn_do.go diff --git a/geg/database/redis/gredis_conn_do_var.go b/geg/database/gredis/gredis_conn_do_var.go similarity index 100% rename from geg/database/redis/gredis_conn_do_var.go rename to geg/database/gredis/gredis_conn_do_var.go diff --git a/geg/database/redis/gredis_conn_send.go b/geg/database/gredis/gredis_conn_send.go similarity index 100% rename from geg/database/redis/gredis_conn_send.go rename to geg/database/gredis/gredis_conn_send.go diff --git a/geg/database/redis/gredis_conn_send_var.go b/geg/database/gredis/gredis_conn_send_var.go similarity index 100% rename from geg/database/redis/gredis_conn_send_var.go rename to geg/database/gredis/gredis_conn_send_var.go diff --git a/geg/database/redis/gredis_conn_subscribe.go b/geg/database/gredis/gredis_conn_subscribe.go similarity index 100% rename from geg/database/redis/gredis_conn_subscribe.go rename to geg/database/gredis/gredis_conn_subscribe.go diff --git a/geg/database/redis/gredis_conn_subscribe_var.go b/geg/database/gredis/gredis_conn_subscribe_var.go similarity index 100% rename from geg/database/redis/gredis_conn_subscribe_var.go rename to geg/database/gredis/gredis_conn_subscribe_var.go diff --git a/geg/net/ghttp/server/log/log.go b/geg/net/ghttp/server/log/log.go new file mode 100644 index 000000000..55ec3fb85 --- /dev/null +++ b/geg/net/ghttp/server/log/log.go @@ -0,0 +1,25 @@ +package main + +import ( + "github.com/gogf/gf/g/net/ghttp" + "net/http" +) + +func main() { + s := ghttp.GetServer() + s.BindHandler("/log/handler", func(r *ghttp.Request) { + r.Response.WriteStatus(http.StatusNotFound, "文件找不到了") + }) + s.SetAccessLogEnabled(true) + s.SetErrorLogEnabled(true) + //s.SetLogHandler(func(r *ghttp.Request, error ...interface{}) { + // if len(error) > 0 { + // // 如果是错误日志 + // fmt.Println("错误产生了:", error[0]) + // } + // // 这里是请求日志 + // fmt.Println("请求处理完成,请求地址:", r.URL.String(), "请求结果:", r.Response.Status) + //}) + s.SetPort(8199) + s.Run() +} diff --git a/geg/net/ghttp/server/log/log_error.go b/geg/net/ghttp/server/log/log_error.go new file mode 100644 index 000000000..02cc6cd11 --- /dev/null +++ b/geg/net/ghttp/server/log/log_error.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/gogf/gf/g/net/ghttp" +) + +func main() { + s := ghttp.GetServer() + s.BindHandler("/log/error", func(r *ghttp.Request) { + if j := r.GetJson(); j != nil { + r.Response.Write(j.Get("test")) + } + }) + s.SetErrorLogEnabled(true) + s.SetPort(8199) + s.Run() +} diff --git a/geg/net/scanner.go b/geg/net/scanner.go deleted file mode 100644 index 259da0bfe..000000000 --- a/geg/net/scanner.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "fmt" - "github.com/gogf/gf/g/net/gscanner" - "net" - "time" -) - -func main() { - //gscanner.New().SetTimeout(3*time.Second).ScanIp("192.168.2.1", "192.168.2.255", 80, func(conn net.Conn){ - // fmt.Println(conn.RemoteAddr()) - //}) - - gscanner.New().SetTimeout(3*time.Second).ScanIp("120.76.249.1", "120.76.249.255", 80, func(conn net.Conn) { - fmt.Println(conn.RemoteAddr()) - }) - - //gscanner.New().SetTimeout(6*time.Second).ScanPort("120.76.249.2", func(conn net.Conn){ - // //fmt.Println("yes") - // fmt.Println(conn.RemoteAddr()) - //}) -} diff --git a/geg/other/test.go b/geg/other/test.go index 790580777..42a1b9963 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,5 +1,28 @@ package main -func main() { +import ( + "github.com/gogf/gf/g/os/glog" + "github.com/gogf/gf/g/os/gcache" +) + +func localCache() { + result := gcache.GetOrSetFunc("test.key.1", func() interface{} { + return nil + }, 1000*60*2) + if result == nil { + glog.Error("未获取到值") + } else { + glog.Infofln("result is $v", result) + } +} + +func TestCache() { + for i := 0; i < 100; i++ { + localCache() + } +} + +func main() { + TestCache() } diff --git a/version.go b/version.go index ad997480a..ca2f542ef 100644 --- a/version.go +++ b/version.go @@ -1,4 +1,4 @@ package gf -const VERSION = "v1.7.0" +const VERSION = "v1.7.1" const AUTHORS = "john"