mirror of
https://gitee.com/johng/gf
synced 2026-06-09 11:03:59 +08:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2636f8acf1 | |||
| 9042a885fa | |||
| ef837bd9c6 | |||
| 6a76725d64 | |||
| 697dbdc604 | |||
| 86f98f3710 | |||
| 470c696976 | |||
| e61bd174c8 | |||
| c71b9bc122 | |||
| c5339cbbe7 | |||
| 29020b0ac0 | |||
| 0a0530af0a | |||
| a5783ab860 | |||
| ae2de91b4c | |||
| ceecbef586 |
@ -9,7 +9,6 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
@ -615,7 +614,8 @@ func (a *IntArray) CountValues() map[int]int {
|
||||
func (a *IntArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return fmt.Sprint(a.array)
|
||||
jsonContent, _ := json.Marshal(a.array)
|
||||
return string(jsonContent)
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
|
||||
@ -9,7 +9,6 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
@ -609,7 +608,8 @@ func (a *Array) CountValues() map[interface{}]int {
|
||||
func (a *Array) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return fmt.Sprint(a.array)
|
||||
jsonContent, _ := json.Marshal(a.array)
|
||||
return string(jsonContent)
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
|
||||
@ -9,7 +9,6 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -615,7 +614,8 @@ func (a *StringArray) CountValues() map[string]int {
|
||||
func (a *StringArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return fmt.Sprint(a.array)
|
||||
jsonContent, _ := json.Marshal(a.array)
|
||||
return string(jsonContent)
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
|
||||
@ -9,7 +9,6 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
@ -540,7 +539,8 @@ func (a *SortedIntArray) CountValues() map[int]int {
|
||||
func (a *SortedIntArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return fmt.Sprint(a.array)
|
||||
jsonContent, _ := json.Marshal(a.array)
|
||||
return string(jsonContent)
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
|
||||
@ -9,7 +9,6 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
@ -541,7 +540,8 @@ func (a *SortedArray) CountValues() map[interface{}]int {
|
||||
func (a *SortedArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return fmt.Sprint(a.array)
|
||||
jsonContent, _ := json.Marshal(a.array)
|
||||
return string(jsonContent)
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
|
||||
@ -9,7 +9,6 @@ package garray
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -535,7 +534,8 @@ func (a *SortedStringArray) CountValues() map[string]int {
|
||||
func (a *SortedStringArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
return fmt.Sprint(a.array)
|
||||
jsonContent, _ := json.Marshal(a.array)
|
||||
return string(jsonContent)
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
|
||||
@ -8,6 +8,7 @@ package glist
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
|
||||
@ -407,17 +408,18 @@ func TestList_PushBacks(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestList_PopBacks(t *testing.T) {
|
||||
l := New()
|
||||
a1 := []interface{}{1, 2, 3, 4}
|
||||
a2 := []interface{}{"a", "c", "b", "e"}
|
||||
l.PushFronts(a1)
|
||||
i1 := l.PopBacks(2)
|
||||
gtest.Assert(i1, []interface{}{"1", "2"})
|
||||
|
||||
l.PushBacks(a2) //4.3,a,c,b,e
|
||||
i1 = l.PopBacks(3)
|
||||
gtest.Assert(i1, []interface{}{"e", "b", "c"})
|
||||
gtest.Case(t, func() {
|
||||
l := New()
|
||||
a1 := []interface{}{1, 2, 3, 4}
|
||||
a2 := []interface{}{"a", "c", "b", "e"}
|
||||
l.PushFronts(a1)
|
||||
i1 := l.PopBacks(2)
|
||||
gtest.Assert(i1, []interface{}{1, 2})
|
||||
|
||||
l.PushBacks(a2) //4.3,a,c,b,e
|
||||
i1 = l.PopBacks(3)
|
||||
gtest.Assert(i1, []interface{}{"e", "b", "c"})
|
||||
})
|
||||
}
|
||||
|
||||
func TestList_PopFronts(t *testing.T) {
|
||||
@ -425,7 +427,7 @@ func TestList_PopFronts(t *testing.T) {
|
||||
a1 := []interface{}{1, 2, 3, 4}
|
||||
l.PushFronts(a1)
|
||||
i1 := l.PopFronts(2)
|
||||
gtest.Assert(i1, []interface{}{"4", "3"})
|
||||
gtest.Assert(i1, []interface{}{4, 3})
|
||||
gtest.Assert(l.Len(), 2)
|
||||
}
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ func New(limit ...int) *Queue {
|
||||
q := &Queue{
|
||||
closed: gtype.NewBool(),
|
||||
}
|
||||
if len(limit) > 0 {
|
||||
if len(limit) > 0 && limit[0] > 0 {
|
||||
q.limit = limit[0]
|
||||
q.C = make(chan interface{}, limit[0])
|
||||
} else {
|
||||
@ -87,7 +87,7 @@ func (q *Queue) startAsyncLoop() {
|
||||
<-q.events
|
||||
}
|
||||
}
|
||||
// It should be here to close q.C.
|
||||
// It should be here to close q.C if <q> is unlimited size.
|
||||
// It's the sender's responsibility to close channel when it should be closed.
|
||||
close(q.C)
|
||||
}
|
||||
@ -119,6 +119,9 @@ func (q *Queue) Close() {
|
||||
if q.events != nil {
|
||||
close(q.events)
|
||||
}
|
||||
if q.limit > 0 {
|
||||
close(q.C)
|
||||
}
|
||||
for i := 0; i < gDEFAULT_MAX_BATCH_SIZE; i++ {
|
||||
q.Pop()
|
||||
}
|
||||
|
||||
@ -95,9 +95,11 @@ type DB interface {
|
||||
getCache() *gcache.Cache
|
||||
getChars() (charLeft string, charRight string)
|
||||
getDebug() bool
|
||||
quoteWord(s string) string
|
||||
setSchema(sqlDb *sql.DB, schema string) error
|
||||
filterFields(table string, data map[string]interface{}) map[string]interface{}
|
||||
convertValue(fieldValue interface{}, fieldType string) interface{}
|
||||
formatWhere(where interface{}, args []interface{}) (newWhere string, newArgs []interface{})
|
||||
convertValue(fieldValue []byte, fieldType string) interface{}
|
||||
getTableFields(table string) (map[string]string, error)
|
||||
rowsToResult(rows *sql.Rows) (Result, error)
|
||||
handleSqlBeforeExec(sql string) string
|
||||
|
||||
@ -8,10 +8,13 @@
|
||||
package gdb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/text/gstr"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/g/container/gvar"
|
||||
@ -26,6 +29,11 @@ const (
|
||||
gDEFAULT_DEBUG_SQL_LENGTH = 1000
|
||||
)
|
||||
|
||||
var (
|
||||
// 用于可转义的单词的识别正则对象
|
||||
wordReg = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`)
|
||||
)
|
||||
|
||||
// 获取最近一条执行的sql
|
||||
func (bs *dbBase) GetLastSql() *Sql {
|
||||
if bs.sqls == nil {
|
||||
@ -311,6 +319,7 @@ func (bs *dbBase) doInsert(link dbLink, table string, data interface{}, option i
|
||||
var values []string
|
||||
var params []interface{}
|
||||
var dataMap Map
|
||||
table = bs.db.quoteWord(table)
|
||||
// 使用反射判断data数据类型,如果为slice类型,那么自动转为批量操作
|
||||
rv := reflect.ValueOf(data)
|
||||
kind := rv.Kind()
|
||||
@ -339,16 +348,16 @@ func (bs *dbBase) doInsert(link dbLink, table string, data interface{}, option i
|
||||
operation := getInsertOperationByOption(option)
|
||||
updateStr := ""
|
||||
if option == OPTION_SAVE {
|
||||
var updates []string
|
||||
for k, _ := range dataMap {
|
||||
updates = append(updates,
|
||||
fmt.Sprintf("%s%s%s=VALUES(%s%s%s)",
|
||||
charL, k, charR,
|
||||
charL, k, charR,
|
||||
),
|
||||
if len(updateStr) > 0 {
|
||||
updateStr += ","
|
||||
}
|
||||
updateStr += fmt.Sprintf("%s%s%s=VALUES(%s%s%s)",
|
||||
charL, k, charR,
|
||||
charL, k, charR,
|
||||
)
|
||||
}
|
||||
updateStr = fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", strings.Join(updates, ","))
|
||||
updateStr = fmt.Sprintf(" ON DUPLICATE KEY UPDATE %s", updateStr)
|
||||
}
|
||||
if link == nil {
|
||||
if link, err = bs.db.Master(); err != nil {
|
||||
@ -381,6 +390,7 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
|
||||
var keys []string
|
||||
var values []string
|
||||
var params []interface{}
|
||||
table = bs.db.quoteWord(table)
|
||||
listMap := (List)(nil)
|
||||
switch v := list.(type) {
|
||||
case Result:
|
||||
@ -432,22 +442,22 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
|
||||
}
|
||||
batchResult := new(batchSqlResult)
|
||||
charL, charR := bs.db.getChars()
|
||||
keyStr := charL + strings.Join(keys, charL+","+charR) + charR
|
||||
keyStr := charL + strings.Join(keys, charR+","+charL) + charR
|
||||
valueHolderStr := "(" + strings.Join(holders, ",") + ")"
|
||||
// 操作判断
|
||||
operation := getInsertOperationByOption(option)
|
||||
updateStr := ""
|
||||
if option == OPTION_SAVE {
|
||||
var updates []string
|
||||
for _, k := range keys {
|
||||
updates = append(updates,
|
||||
fmt.Sprintf("%s%s%s=VALUES(%s%s%s)",
|
||||
charL, k, charR,
|
||||
charL, k, charR,
|
||||
),
|
||||
if len(updateStr) > 0 {
|
||||
updateStr += ","
|
||||
}
|
||||
updateStr += fmt.Sprintf("%s%s%s=VALUES(%s%s%s)",
|
||||
charL, k, charR,
|
||||
charL, k, charR,
|
||||
)
|
||||
}
|
||||
updateStr = fmt.Sprintf(" ON DUPLICATE KEY UPDATE %s", strings.Join(updates, ","))
|
||||
updateStr = fmt.Sprintf(" ON DUPLICATE KEY UPDATE %s", updateStr)
|
||||
}
|
||||
// 构造批量写入数据格式(注意map的遍历是无序的)
|
||||
batchNum := gDEFAULT_BATCH_NUM
|
||||
@ -499,7 +509,7 @@ 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 := formatWhere(condition, args)
|
||||
newWhere, newArgs := bs.db.formatWhere(condition, args)
|
||||
if newWhere != "" {
|
||||
newWhere = " WHERE " + newWhere
|
||||
}
|
||||
@ -509,8 +519,8 @@ func (bs *dbBase) Update(table string, data interface{}, condition interface{},
|
||||
// CURD操作:数据更新,统一采用sql预处理。
|
||||
// data参数支持string/map/struct/*struct类型类型。
|
||||
func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error) {
|
||||
table = bs.db.quoteWord(table)
|
||||
updates := ""
|
||||
charL, charR := bs.db.getChars()
|
||||
// 使用反射进行类型判断
|
||||
rv := reflect.ValueOf(data)
|
||||
kind := rv.Kind()
|
||||
@ -525,7 +535,7 @@ func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, conditio
|
||||
case reflect.Struct:
|
||||
var fields []string
|
||||
for k, v := range structToMap(data) {
|
||||
fields = append(fields, fmt.Sprintf("%s%s%s=?", charL, k, charR))
|
||||
fields = append(fields, bs.db.quoteWord(k)+"=?")
|
||||
params = append(params, convertParam(v))
|
||||
}
|
||||
updates = strings.Join(fields, ",")
|
||||
@ -546,7 +556,7 @@ func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, conditio
|
||||
|
||||
// CURD操作:删除数据
|
||||
func (bs *dbBase) Delete(table string, condition interface{}, args ...interface{}) (result sql.Result, err error) {
|
||||
newWhere, newArgs := formatWhere(condition, args)
|
||||
newWhere, newArgs := bs.db.formatWhere(condition, args)
|
||||
if newWhere != "" {
|
||||
newWhere = " WHERE " + newWhere
|
||||
}
|
||||
@ -560,6 +570,7 @@ func (bs *dbBase) doDelete(link dbLink, table string, condition string, args ...
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
table = bs.db.quoteWord(table)
|
||||
return bs.db.doExec(link, fmt.Sprintf("DELETE FROM %s%s", table, condition), args...)
|
||||
}
|
||||
|
||||
@ -605,6 +616,7 @@ func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) {
|
||||
// 由于 sql.RawBytes 是slice类型, 这里必须使用值复制
|
||||
v := make([]byte, len(column))
|
||||
copy(v, column)
|
||||
//fmt.Println(columns[i], types[i], string(v), v, bs.db.convertValue(v, types[i]))
|
||||
row[columns[i]] = gvar.New(bs.db.convertValue(v, types[i]), true)
|
||||
}
|
||||
}
|
||||
@ -616,6 +628,98 @@ func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) {
|
||||
return records, nil
|
||||
}
|
||||
|
||||
// 格式化Where查询条件。
|
||||
func (bs *dbBase) formatWhere(where interface{}, args []interface{}) (newWhere string, newArgs []interface{}) {
|
||||
// 条件字符串处理
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
// 使用反射进行类型判断
|
||||
rv := reflect.ValueOf(where)
|
||||
kind := rv.Kind()
|
||||
if kind == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
kind = rv.Kind()
|
||||
}
|
||||
switch kind {
|
||||
// map/struct类型
|
||||
case reflect.Map:
|
||||
fallthrough
|
||||
case reflect.Struct:
|
||||
for key, value := range structToMap(where) {
|
||||
// 字段安全符号判断
|
||||
key = bs.db.quoteWord(key)
|
||||
if buffer.Len() > 0 {
|
||||
buffer.WriteString(" AND ")
|
||||
}
|
||||
// 支持slice键值/属性,如果只有一个?占位符号,那么作为IN查询,否则打散作为多个查询参数
|
||||
rv := reflect.ValueOf(value)
|
||||
switch rv.Kind() {
|
||||
case reflect.Slice:
|
||||
fallthrough
|
||||
case reflect.Array:
|
||||
count := gstr.Count(key, "?")
|
||||
if count == 0 {
|
||||
buffer.WriteString(key + " IN(?)")
|
||||
newArgs = append(newArgs, value)
|
||||
} else if count != rv.Len() {
|
||||
buffer.WriteString(key)
|
||||
newArgs = append(newArgs, value)
|
||||
} else {
|
||||
buffer.WriteString(key)
|
||||
// 如果键名/属性名称中带有多个?占位符号,那么将参数打散
|
||||
newArgs = append(newArgs, gconv.Interfaces(value)...)
|
||||
}
|
||||
default:
|
||||
if value == nil {
|
||||
buffer.WriteString(key)
|
||||
} else {
|
||||
// 支持key带操作符号
|
||||
if gstr.Pos(key, "?") == -1 {
|
||||
if gstr.Pos(key, "<") == -1 && gstr.Pos(key, ">") == -1 && gstr.Pos(key, "=") == -1 {
|
||||
buffer.WriteString(key + "=?")
|
||||
} else {
|
||||
buffer.WriteString(key + "?")
|
||||
}
|
||||
} else {
|
||||
buffer.WriteString(key)
|
||||
}
|
||||
newArgs = append(newArgs, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
buffer.WriteString(gconv.String(where))
|
||||
}
|
||||
// 没有任何条件查询参数,直接返回
|
||||
if buffer.Len() == 0 {
|
||||
return "", args
|
||||
}
|
||||
newArgs = append(newArgs, args...)
|
||||
newWhere = buffer.String()
|
||||
// 查询条件参数处理,主要处理slice参数类型
|
||||
if len(newArgs) > 0 {
|
||||
// 支持例如 Where/And/Or("uid", 1) 这种格式
|
||||
if gstr.Pos(newWhere, "?") == -1 {
|
||||
if gstr.Pos(newWhere, "<") == -1 && gstr.Pos(newWhere, ">") == -1 && gstr.Pos(newWhere, "=") == -1 {
|
||||
newWhere += "=?"
|
||||
} else {
|
||||
newWhere += "?"
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 使用关键字操作符转义给定字符串。
|
||||
// 如果给定的字符串不为单词,那么不转义,直接返回该字符串。
|
||||
func (bs *dbBase) quoteWord(s string) string {
|
||||
charLeft, charRight := bs.db.getChars()
|
||||
if wordReg.MatchString(s) && !gstr.ContainsAny(s, charLeft+charRight) {
|
||||
return charLeft + s + charRight
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// 动态切换数据库
|
||||
func (bs *dbBase) setSchema(sqlDb *sql.DB, schema string) error {
|
||||
_, err := sqlDb.Exec("USE " + schema)
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
package gdb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -44,6 +43,11 @@ func formatQuery(query string, args []interface{}) (newQuery string, newArgs []i
|
||||
switch kind {
|
||||
// '?'占位符支持slice类型, 这里会将slice参数拆散,并更新原有占位符'?'为多个'?',使用','符号连接。
|
||||
case reflect.Slice, reflect.Array:
|
||||
// 不拆分[]byte类型
|
||||
if _, ok := arg.([]byte); ok {
|
||||
newArgs = append(newArgs, arg)
|
||||
continue
|
||||
}
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
newArgs = append(newArgs, rv.Index(i).Interface())
|
||||
}
|
||||
@ -69,86 +73,6 @@ func formatQuery(query string, args []interface{}) (newQuery string, newArgs []i
|
||||
return
|
||||
}
|
||||
|
||||
// 格式化Where查询条件。
|
||||
func formatWhere(where interface{}, args []interface{}) (newWhere string, newArgs []interface{}) {
|
||||
// 条件字符串处理
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
// 使用反射进行类型判断
|
||||
rv := reflect.ValueOf(where)
|
||||
kind := rv.Kind()
|
||||
if kind == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
kind = rv.Kind()
|
||||
}
|
||||
switch kind {
|
||||
// map/struct类型
|
||||
case reflect.Map:
|
||||
fallthrough
|
||||
case reflect.Struct:
|
||||
for key, value := range structToMap(where) {
|
||||
if buffer.Len() > 0 {
|
||||
buffer.WriteString(" AND ")
|
||||
}
|
||||
// 支持slice键值/属性,如果只有一个?占位符号,那么作为IN查询,否则打散作为多个查询参数
|
||||
rv := reflect.ValueOf(value)
|
||||
switch rv.Kind() {
|
||||
case reflect.Slice:
|
||||
fallthrough
|
||||
case reflect.Array:
|
||||
count := gstr.Count(key, "?")
|
||||
if count == 0 {
|
||||
buffer.WriteString(key + " IN(?)")
|
||||
newArgs = append(newArgs, value)
|
||||
} else if count != rv.Len() {
|
||||
buffer.WriteString(key)
|
||||
newArgs = append(newArgs, value)
|
||||
} else {
|
||||
buffer.WriteString(key)
|
||||
// 如果键名/属性名称中带有多个?占位符号,那么将参数打散
|
||||
newArgs = append(newArgs, gconv.Interfaces(value)...)
|
||||
}
|
||||
default:
|
||||
if value == nil {
|
||||
buffer.WriteString(key)
|
||||
} else {
|
||||
// 支持key带操作符号
|
||||
if gstr.Pos(key, "?") == -1 {
|
||||
if gstr.Pos(key, "<") == -1 && gstr.Pos(key, ">") == -1 && gstr.Pos(key, "=") == -1 {
|
||||
buffer.WriteString(key + "=?")
|
||||
} else {
|
||||
buffer.WriteString(key + "?")
|
||||
}
|
||||
} else {
|
||||
buffer.WriteString(key)
|
||||
}
|
||||
newArgs = append(newArgs, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
buffer.WriteString(gconv.String(where))
|
||||
}
|
||||
// 没有任何条件查询参数,直接返回
|
||||
if buffer.Len() == 0 {
|
||||
return "", args
|
||||
}
|
||||
newArgs = append(newArgs, args...)
|
||||
newWhere = buffer.String()
|
||||
// 查询条件参数处理,主要处理slice参数类型
|
||||
if len(newArgs) > 0 {
|
||||
// 支持例如 Where/And/Or("uid", 1) 这种格式
|
||||
if gstr.Pos(newWhere, "?") == -1 {
|
||||
if gstr.Pos(newWhere, "<") == -1 && gstr.Pos(newWhere, ">") == -1 && gstr.Pos(newWhere, "=") == -1 {
|
||||
newWhere += "=?"
|
||||
} else {
|
||||
newWhere += "?"
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 将预处理参数转换为底层数据库引擎支持的格式。
|
||||
// 主要是判断参数是否为复杂数据类型,如果是,那么转换为基础类型。
|
||||
func convertParam(value interface{}) interface{} {
|
||||
|
||||
@ -43,7 +43,7 @@ func (bs *dbBase) Table(tables string) *Model {
|
||||
return &Model{
|
||||
db: bs.db,
|
||||
tablesInit: tables,
|
||||
tables: tables,
|
||||
tables: bs.db.quoteWord(tables),
|
||||
fields: "*",
|
||||
start: -1,
|
||||
offset: -1,
|
||||
@ -62,7 +62,7 @@ func (tx *TX) Table(tables string) *Model {
|
||||
db: tx.db,
|
||||
tx: tx,
|
||||
tablesInit: tables,
|
||||
tables: tables,
|
||||
tables: tx.db.quoteWord(tables),
|
||||
fields: "*",
|
||||
start: -1,
|
||||
offset: -1,
|
||||
@ -154,7 +154,7 @@ func (md *Model) Where(where interface{}, args ...interface{}) *Model {
|
||||
if model.where != "" {
|
||||
return md.And(where, args...)
|
||||
}
|
||||
newWhere, newArgs := formatWhere(where, args)
|
||||
newWhere, newArgs := md.db.formatWhere(where, args)
|
||||
model.where = newWhere
|
||||
model.whereArgs = newArgs
|
||||
return model
|
||||
@ -163,7 +163,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 := formatWhere(where, args)
|
||||
newWhere, newArgs := md.db.formatWhere(where, args)
|
||||
if len(model.where) > 0 && model.where[0] == '(' {
|
||||
model.where = fmt.Sprintf(`%s AND (%s)`, model.where, newWhere)
|
||||
} else {
|
||||
@ -176,7 +176,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 := formatWhere(where, args)
|
||||
newWhere, newArgs := md.db.formatWhere(where, args)
|
||||
if len(model.where) > 0 && model.where[0] == '(' {
|
||||
model.where = fmt.Sprintf(`%s OR (%s)`, model.where, newWhere)
|
||||
} else {
|
||||
@ -474,7 +474,7 @@ func (md *Model) Select() (Result, error) {
|
||||
|
||||
// 链式操作,查询所有记录
|
||||
func (md *Model) All() (Result, error) {
|
||||
return md.getAll(fmt.Sprintf("SELECT %s FROM %s %s", md.fields, md.tables, md.getConditionSql()), md.whereArgs...)
|
||||
return md.getAll(fmt.Sprintf("SELECT %s FROM %s%s", md.fields, md.tables, md.getConditionSql()), md.whereArgs...)
|
||||
}
|
||||
|
||||
// 链式操作,查询单条记录
|
||||
|
||||
@ -25,24 +25,24 @@ import (
|
||||
//}
|
||||
|
||||
// 字段类型转换,将数据库字段类型转换为golang变量类型
|
||||
func (bs *dbBase) convertValue(fieldValue interface{}, fieldType string) interface{} {
|
||||
func (bs *dbBase) convertValue(fieldValue []byte, fieldType string) interface{} {
|
||||
t, _ := gregex.ReplaceString(`\(.+\)`, "", fieldType)
|
||||
t = strings.ToLower(t)
|
||||
switch t {
|
||||
case "binary", "varbinary", "blob", "tinyblob", "mediumblob", "longblob":
|
||||
return gconv.Bytes(fieldValue)
|
||||
return fieldValue
|
||||
|
||||
case "int", "tinyint", "small_int", "medium_int":
|
||||
return gconv.Int(fieldValue)
|
||||
return gconv.Int(string(fieldValue))
|
||||
|
||||
case "big_int":
|
||||
return gconv.Int64(fieldValue)
|
||||
return gconv.Int64(string(fieldValue))
|
||||
|
||||
case "float", "double", "decimal":
|
||||
return gconv.Float64(fieldValue)
|
||||
return gconv.Float64(string(fieldValue))
|
||||
|
||||
case "bit":
|
||||
s := gconv.String(fieldValue)
|
||||
s := string(fieldValue)
|
||||
// 这里的字符串判断是为兼容不同的数据库类型,如: mssql
|
||||
if strings.EqualFold(s, "true") {
|
||||
return 1
|
||||
@ -50,10 +50,7 @@ func (bs *dbBase) convertValue(fieldValue interface{}, fieldType string) interfa
|
||||
if strings.EqualFold(s, "false") {
|
||||
return 0
|
||||
}
|
||||
if b, ok := fieldValue.([]byte); ok {
|
||||
return gbinary.BeDecodeToInt64(b)
|
||||
}
|
||||
return gconv.Int(fieldValue)
|
||||
return gbinary.BeDecodeToInt64(fieldValue)
|
||||
|
||||
case "bool":
|
||||
return gconv.Bool(fieldValue)
|
||||
@ -62,22 +59,22 @@ func (bs *dbBase) convertValue(fieldValue interface{}, fieldType string) interfa
|
||||
// 自动识别类型, 以便默认支持更多数据库类型
|
||||
switch {
|
||||
case strings.Contains(t, "int"):
|
||||
return gconv.Int(fieldValue)
|
||||
return gconv.Int(string(fieldValue))
|
||||
|
||||
case strings.Contains(t, "text") || strings.Contains(t, "char"):
|
||||
return gconv.String(fieldValue)
|
||||
return string(fieldValue)
|
||||
|
||||
case strings.Contains(t, "float") || strings.Contains(t, "double"):
|
||||
return gconv.Float64(fieldValue)
|
||||
return gconv.Float64(string(fieldValue))
|
||||
|
||||
case strings.Contains(t, "bool"):
|
||||
return gconv.Bool(fieldValue)
|
||||
return gconv.Bool(string(fieldValue))
|
||||
|
||||
case strings.Contains(t, "binary") || strings.Contains(t, "blob"):
|
||||
return gconv.Bytes(fieldValue)
|
||||
return fieldValue
|
||||
|
||||
default:
|
||||
return gconv.String(fieldValue)
|
||||
return string(fieldValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,8 +96,7 @@ func (bs *dbBase) getTableFields(table string) (fields map[string]string, err er
|
||||
// 缓存不存在时会查询数据表结构,缓存后不过期,直至程序重启(重新部署)
|
||||
v := bs.cache.GetOrSetFunc("table_fields_"+table, func() interface{} {
|
||||
result := (Result)(nil)
|
||||
charL, charR := bs.db.getChars()
|
||||
result, err = bs.GetAll(fmt.Sprintf(`SHOW COLUMNS FROM %s%s%s`, charL, table, charR))
|
||||
result, err = bs.GetAll(fmt.Sprintf(`SHOW COLUMNS FROM %s`, bs.db.quoteWord(table)))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ 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 := formatWhere(condition, args)
|
||||
newWhere, newArgs := tx.db.formatWhere(condition, args)
|
||||
if newWhere != "" {
|
||||
newWhere = " WHERE " + newWhere
|
||||
}
|
||||
@ -179,7 +179,7 @@ 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 := formatWhere(condition, args)
|
||||
newWhere, newArgs := tx.db.formatWhere(condition, args)
|
||||
if newWhere != "" {
|
||||
newWhere = " WHERE " + newWhere
|
||||
}
|
||||
|
||||
60
g/database/gdb/gdb_unit_types_test.go
Normal file
60
g/database/gdb/gdb_unit_types_test.go
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// 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 gdb_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g"
|
||||
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Types(t *testing.T) {
|
||||
|
||||
gtest.Case(t, func() {
|
||||
if _, err := db.Exec(fmt.Sprintf(`
|
||||
CREATE TABLE IF NOT EXISTS types (
|
||||
id int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
%s blob NOT NULL,
|
||||
%s binary(8) NOT NULL,
|
||||
%s date NOT NULL,
|
||||
%s decimal(5,2) NOT NULL,
|
||||
%s double NOT NULL,
|
||||
%s bit(2) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`, "`blob`", "`binary`", "`date`", "`decimal`", "`double`", "`bit`")); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
defer dropTable("types")
|
||||
data := g.Map{
|
||||
"id": 1,
|
||||
"blob": "i love gf",
|
||||
"binary": []byte("abcdefgh"),
|
||||
"date": "2018-10-24",
|
||||
"decimal": 123.456,
|
||||
"double": 123.456,
|
||||
"bit": 2,
|
||||
}
|
||||
r, err := db.Table("types").Data(data).Insert()
|
||||
gtest.Assert(err, nil)
|
||||
n, _ := r.RowsAffected()
|
||||
gtest.Assert(n, 1)
|
||||
|
||||
one, err := db.Table("types").One()
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(one["id"].Int(), 1)
|
||||
gtest.Assert(one["blob"].String(), data["blob"])
|
||||
gtest.Assert(one["binary"].String(), data["binary"])
|
||||
gtest.Assert(one["date"].String(), data["date"])
|
||||
gtest.Assert(one["decimal"].String(), 123.46)
|
||||
gtest.Assert(one["double"].String(), data["double"])
|
||||
gtest.Assert(one["bit"].Int(), data["bit"])
|
||||
})
|
||||
}
|
||||
@ -327,7 +327,7 @@ func Test_TX_Update(t *testing.T) {
|
||||
if err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
if result, err := db.Update(table, "create_time='2019-10-24 10:00:00'", "id=3"); err != nil {
|
||||
if result, err := tx.Update(table, "create_time='2019-10-24 10:00:00'", "id=3"); err != nil {
|
||||
gtest.Error(err)
|
||||
} else {
|
||||
n, _ := result.RowsAffected()
|
||||
@ -336,6 +336,9 @@ func Test_TX_Update(t *testing.T) {
|
||||
if err := tx.Commit(); err != nil {
|
||||
gtest.Error(err)
|
||||
}
|
||||
_, err = tx.Table(table).Fields("create_time").Where("id", 3).Value()
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
if value, err := db.Table(table).Fields("create_time").Where("id", 3).Value(); err != nil {
|
||||
gtest.Error(err)
|
||||
} else {
|
||||
|
||||
@ -27,9 +27,7 @@ type Json struct {
|
||||
mu *rwmutex.RWMutex
|
||||
p *interface{} // Pointer for hierarchical data access, it's the root of data in default.
|
||||
c byte // Char separator('.' in default).
|
||||
// Violence Check(false in default), which is used to access data
|
||||
// when the hierarchical data key contains separator char.
|
||||
vc bool
|
||||
vc bool // Violence Check(false in default), which is used to access data when the hierarchical data key contains separator char.
|
||||
}
|
||||
|
||||
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
|
||||
@ -37,8 +35,8 @@ func (j *Json) MarshalJSON() ([]byte, error) {
|
||||
return j.ToJson()
|
||||
}
|
||||
|
||||
// Set <value> by <pattern>.
|
||||
// Notice:
|
||||
// setValue sets <value> to <j> by <pattern>.
|
||||
// Note:
|
||||
// 1. If value is nil and removed is true, means deleting this value;
|
||||
// 2. It's quite complicated in hierarchical data search, node creating and data assignment;
|
||||
func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
@ -53,8 +51,8 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
*j.p = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
var pparent *interface{} = nil // 父级元素项(设置时需要根据子级的内容确定数据类型,所以必须记录父级)
|
||||
var pointer *interface{} = j.p // 当前操作层级项
|
||||
var pparent *interface{} = nil // Parent pointer.
|
||||
var pointer *interface{} = j.p // Current pointer.
|
||||
j.mu.Lock()
|
||||
defer j.mu.Unlock()
|
||||
for i := 0; i < length; i++ {
|
||||
@ -62,26 +60,26 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
case map[string]interface{}:
|
||||
if i == length-1 {
|
||||
if removed && value == nil {
|
||||
// 删除map元素
|
||||
// Delete item from map.
|
||||
delete((*pointer).(map[string]interface{}), array[i])
|
||||
} else {
|
||||
(*pointer).(map[string]interface{})[array[i]] = value
|
||||
}
|
||||
} else {
|
||||
// 当键名不存在的情况这里会进行处理
|
||||
// If the key does not exit in the map.
|
||||
if v, ok := (*pointer).(map[string]interface{})[array[i]]; !ok {
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
}
|
||||
// 创建新节点
|
||||
// Creating new node.
|
||||
if gstr.IsNumeric(array[i+1]) {
|
||||
// 创建array节点
|
||||
// Creating array node.
|
||||
n, _ := strconv.Atoi(array[i+1])
|
||||
var v interface{} = make([]interface{}, n+1)
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
} else {
|
||||
// 创建map节点
|
||||
// Creating map node.
|
||||
var v interface{} = make(map[string]interface{})
|
||||
pparent = j.setPointerWithValue(pointer, array[i], v)
|
||||
pointer = &v
|
||||
@ -93,7 +91,6 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
}
|
||||
|
||||
case []interface{}:
|
||||
// 键名与当前指针类型不符合,需要执行**覆盖操作**
|
||||
if !gstr.IsNumeric(array[i]) {
|
||||
if i == length-1 {
|
||||
*pointer = map[string]interface{}{array[i]: value}
|
||||
@ -110,11 +107,11 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 叶子节点
|
||||
// Leaf node.
|
||||
if i == length-1 {
|
||||
if len((*pointer).([]interface{})) > valn {
|
||||
if removed && value == nil {
|
||||
// 删除数据元素
|
||||
// Deleting element.
|
||||
if pparent == nil {
|
||||
*pointer = append((*pointer).([]interface{})[:valn], (*pointer).([]interface{})[valn+1:]...)
|
||||
} else {
|
||||
@ -128,10 +125,10 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
goto done
|
||||
}
|
||||
if pparent == nil {
|
||||
// 表示根节点
|
||||
// It is the root node.
|
||||
j.setPointerWithValue(pointer, array[i], value)
|
||||
} else {
|
||||
// 非根节点
|
||||
// It is not the root node.
|
||||
s := make([]interface{}, valn+1)
|
||||
copy(s, (*pointer).([]interface{}))
|
||||
s[valn] = value
|
||||
@ -160,8 +157,8 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
}
|
||||
}
|
||||
|
||||
// 如果当前指针指向的变量不是引用类型的,
|
||||
// 那么修改变量必须通过父级进行修改,即 pparent
|
||||
// If the variable pointed to by the <pointer> is not of a reference type,
|
||||
// then it modifies the variable via its the parent, ie: pparent.
|
||||
default:
|
||||
if removed && value == nil {
|
||||
goto done
|
||||
@ -199,7 +196,7 @@ done:
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert <value> to map[string]interface{} or []interface{},
|
||||
// convertValue converts <value> to map[string]interface{} or []interface{},
|
||||
// which can be supported for hierarchical data access.
|
||||
func (j *Json) convertValue(value interface{}) interface{} {
|
||||
switch value.(type) {
|
||||
@ -232,7 +229,7 @@ func (j *Json) convertValue(value interface{}) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// Set <key>:<value> to <pointer>, the <key> may be a map key or slice index.
|
||||
// setPointerWithValue sets <key>:<value> to <pointer>, the <key> may be a map key or slice index.
|
||||
// It returns the pointer to the new value set.
|
||||
func (j *Json) setPointerWithValue(pointer *interface{}, key string, value interface{}) *interface{} {
|
||||
switch (*pointer).(type) {
|
||||
@ -257,7 +254,7 @@ func (j *Json) setPointerWithValue(pointer *interface{}, key string, value inter
|
||||
return pointer
|
||||
}
|
||||
|
||||
// Get a pointer to the value by specified <pattern>.
|
||||
// getPointerByPattern returns a pointer to the value by specified <pattern>.
|
||||
func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
if j.vc {
|
||||
return j.getPointerByPatternWithViolenceCheck(pattern)
|
||||
@ -266,7 +263,7 @@ func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// Get a pointer to the value of specified <pattern> with violence check.
|
||||
// getPointerByPatternWithViolenceCheck returns a pointer to the value of specified <pattern> with violence check.
|
||||
func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{} {
|
||||
if !j.vc {
|
||||
return j.getPointerByPatternWithoutViolenceCheck(pattern)
|
||||
@ -305,7 +302,7 @@ func (j *Json) getPointerByPatternWithViolenceCheck(pattern string) *interface{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get a pointer to the value of specified <pattern>, with no violence check.
|
||||
// getPointerByPatternWithoutViolenceCheck returns a pointer to the value of specified <pattern>, with no violence check.
|
||||
func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interface{} {
|
||||
if j.vc {
|
||||
return j.getPointerByPatternWithViolenceCheck(pattern)
|
||||
@ -329,7 +326,7 @@ func (j *Json) getPointerByPatternWithoutViolenceCheck(pattern string) *interfac
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check whether there's value by <key> in specified <pointer>.
|
||||
// checkPatternByPointer checks whether there's value by <key> in specified <pointer>.
|
||||
// It returns a pointer to the value.
|
||||
func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interface{} {
|
||||
switch (*pointer).(type) {
|
||||
|
||||
@ -156,6 +156,9 @@ func doLoadContent(dataType string, data []byte, unsafe ...bool) (*Json, error)
|
||||
if len(data) == 0 {
|
||||
return New(nil, unsafe...), nil
|
||||
}
|
||||
if dataType == "" {
|
||||
dataType = checkDataType(data)
|
||||
}
|
||||
switch dataType {
|
||||
case "json", ".json":
|
||||
|
||||
@ -203,14 +206,15 @@ func LoadContent(data interface{}, unsafe ...bool) (*Json, error) {
|
||||
|
||||
}
|
||||
|
||||
// checkDataType automatically checks and returns the data type for <content>.
|
||||
func checkDataType(content []byte) string {
|
||||
if json.Valid(content) {
|
||||
return "json"
|
||||
} else if gregex.IsMatch(`^<.+>[\S\s]+<.+>$`, content) {
|
||||
return "xml"
|
||||
} else if gregex.IsMatch(`^[\s\t]*\w+\s*:\s*.+`, content) || gregex.IsMatch(`\n[\s\t]*\w+\s*:\s*.+`, content) {
|
||||
} else if gregex.IsMatch(`^[\s\t]*[\w\-]+\s*:\s*.+`, content) || gregex.IsMatch(`\n[\s\t]*[\w\-]+\s*:\s*.+`, content) {
|
||||
return "yml"
|
||||
} else if gregex.IsMatch(`^[\s\t]*\w+\s*=\s*.+`, content) || gregex.IsMatch(`\n[\s\t]*\w+\s*=\s*.+`, content) {
|
||||
} else if gregex.IsMatch(`^[\s\t]*[\w\-]+\s*=\s*.+`, content) || gregex.IsMatch(`\n[\s\t]*[\w\-]+\s*=\s*.+`, content) {
|
||||
return "toml"
|
||||
} else {
|
||||
return ""
|
||||
|
||||
@ -51,7 +51,7 @@ func Test_Load_XML(t *testing.T) {
|
||||
gtest.Assert(j.Get("doc.n"), "123456789")
|
||||
gtest.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("doc.m.k"), "v")
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
// XML
|
||||
@ -64,7 +64,7 @@ func Test_Load_XML(t *testing.T) {
|
||||
gtest.Assert(j.Get("doc.n"), "123456789")
|
||||
gtest.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("doc.m.k"), "v")
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
|
||||
@ -146,7 +146,7 @@ n = 123456789
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// TOML
|
||||
@ -159,7 +159,7 @@ n = 123456789
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -7,12 +7,13 @@
|
||||
package gparser_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/encoding/gparser"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Load_JSON(t *testing.T) {
|
||||
@ -51,7 +52,7 @@ func Test_Load_XML(t *testing.T) {
|
||||
gtest.Assert(j.Get("doc.n"), "123456789")
|
||||
gtest.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("doc.m.k"), "v")
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
// XML
|
||||
@ -64,7 +65,7 @@ func Test_Load_XML(t *testing.T) {
|
||||
gtest.Assert(j.Get("doc.n"), "123456789")
|
||||
gtest.Assert(j.Get("doc.m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("doc.m.k"), "v")
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("doc.a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("doc.a.1"), 2)
|
||||
})
|
||||
|
||||
@ -146,7 +147,7 @@ n = "123456789"
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
// TOML
|
||||
@ -159,7 +160,7 @@ n = "123456789"
|
||||
gtest.Assert(j.Get("n"), "123456789")
|
||||
gtest.Assert(j.Get("m"), g.Map{"k": "v"})
|
||||
gtest.Assert(j.Get("m.k"), "v")
|
||||
gtest.Assert(j.Get("a"), g.Slice{1, 2, 3})
|
||||
gtest.Assert(j.Get("a"), g.Slice{"1", "2", "3"})
|
||||
gtest.Assert(j.Get("a.1"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gins_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/os/gcfg"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -167,3 +168,17 @@ test = "v=1"
|
||||
gtest.Assert(gins.Config("test").Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Basic2(t *testing.T) {
|
||||
config := `log-path = "logs"`
|
||||
gtest.Case(t, func() {
|
||||
path := gcfg.DEFAULT_CONFIG_FILE
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer func() {
|
||||
_ = gfile.Remove(path)
|
||||
}()
|
||||
|
||||
gtest.Assert(gins.Config().Get("log-path"), "logs")
|
||||
})
|
||||
}
|
||||
|
||||
@ -55,11 +55,8 @@ func StackWithFilter(filter string, skip ...int) string {
|
||||
space := " "
|
||||
index := 1
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
for i := callerFromIndex() + number; i < gMAX_DEPTH; i++ {
|
||||
for i := callerFromIndex(filter) + number; i < gMAX_DEPTH; i++ {
|
||||
if pc, file, line, ok := runtime.Caller(i); ok {
|
||||
if filter != "" && strings.Contains(file, filter) {
|
||||
continue
|
||||
}
|
||||
if goRootForFilter != "" && len(file) >= len(goRootForFilter) && file[0:len(goRootForFilter)] == goRootForFilter {
|
||||
continue
|
||||
}
|
||||
@ -93,11 +90,8 @@ func CallerWithFilter(filter string, skip ...int) string {
|
||||
if len(skip) > 0 {
|
||||
number = skip[0]
|
||||
}
|
||||
for i := callerFromIndex() + number; i < gMAX_DEPTH; i++ {
|
||||
for i := callerFromIndex(filter) + number; i < gMAX_DEPTH; i++ {
|
||||
if _, file, line, ok := runtime.Caller(i); ok {
|
||||
if filter != "" && strings.Contains(file, filter) {
|
||||
continue
|
||||
}
|
||||
return fmt.Sprintf(`%s:%d`, file, line)
|
||||
} else {
|
||||
break
|
||||
@ -107,9 +101,12 @@ func CallerWithFilter(filter string, skip ...int) string {
|
||||
}
|
||||
|
||||
// callerFromIndex returns the caller position exclusive of the debug package.
|
||||
func callerFromIndex() int {
|
||||
func callerFromIndex(filter string) int {
|
||||
for i := 0; i < gMAX_DEPTH; i++ {
|
||||
if _, file, _, ok := runtime.Caller(i); ok {
|
||||
if filter != "" && strings.Contains(file, filter) {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(file, gFILTER_KEY) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -36,26 +36,21 @@ import (
|
||||
type (
|
||||
// Server结构体
|
||||
Server struct {
|
||||
// 基本属性变量
|
||||
name string // 服务名称,方便识别
|
||||
config ServerConfig // 配置对象
|
||||
servers []*gracefulServer // 底层http.Server列表
|
||||
serverCount *gtype.Int // 底层http.Server数量
|
||||
closeChan chan struct{} // 用以关闭事件通知的通道
|
||||
servedCount *gtype.Int // 已经服务的请求数(4-8字节,不考虑溢出情况),同时作为请求ID
|
||||
// 服务注册相关
|
||||
serveTree map[string]interface{} // 所有注册的服务回调函数(路由表,树型结构,哈希表+链表优先级匹配)
|
||||
hooksTree map[string]interface{} // 所有注册的事件回调函数(路由表,树型结构,哈希表+链表优先级匹配)
|
||||
serveCache *gcache.Cache // 服务注册路由内存缓存
|
||||
hooksCache *gcache.Cache // 事件回调路由内存缓存
|
||||
routesMap map[string][]registeredRouteItem // 已经注册的路由及对应的注册方法文件地址(用以路由重复注册判断)
|
||||
// 自定义状态码回调
|
||||
hsmu sync.RWMutex // status handler互斥锁
|
||||
statusHandlerMap map[string]HandlerFunc // 不同状态码下的注册处理方法(例如404状态时的处理方法)
|
||||
// SESSION
|
||||
sessions *gcache.Cache // Session内存缓存
|
||||
// Logger
|
||||
logger *glog.Logger // 日志管理对象
|
||||
name string // 服务名称
|
||||
config ServerConfig // 配置对象
|
||||
servers []*gracefulServer // 底层http.Server列表
|
||||
serverCount *gtype.Int // 底层http.Server数量
|
||||
closeChan chan struct{} // 用以关闭事件通知的通道
|
||||
servedCount *gtype.Int // 已经服务的请求数(4-8字节,不考虑溢出情况),同时作为请求ID
|
||||
serveTree map[string]interface{} // 所有注册的服务回调函数(路由表,树型结构,哈希表+链表优先级匹配)
|
||||
hooksTree map[string]interface{} // 所有注册的事件回调函数(路由表,树型结构,哈希表+链表优先级匹配)
|
||||
serveCache *gcache.Cache // 服务注册路由内存缓存
|
||||
hooksCache *gcache.Cache // 事件回调路由内存缓存
|
||||
routesMap map[string][]registeredRouteItem // 已经注册的路由及对应的注册方法文件地址(用以路由重复注册判断)
|
||||
statusHandlerMu sync.RWMutex // status handler互斥锁
|
||||
statusHandlerMap map[string]HandlerFunc // 不同状态码下的注册处理方法(例如404状态时的处理方法)
|
||||
sessions *gcache.Cache // Session内存缓存
|
||||
logger *glog.Logger // 日志管理对象
|
||||
}
|
||||
|
||||
// 路由对象
|
||||
@ -103,17 +98,14 @@ type (
|
||||
)
|
||||
|
||||
const (
|
||||
SERVER_STATUS_STOPPED = 0 // Server状态:停止
|
||||
SERVER_STATUS_RUNNING = 1 // Server状态:运行
|
||||
HOOK_BEFORE_SERVE = "BeforeServe"
|
||||
HOOK_AFTER_SERVE = "AfterServe"
|
||||
HOOK_BEFORE_OUTPUT = "BeforeOutput"
|
||||
HOOK_AFTER_OUTPUT = "AfterOutput"
|
||||
|
||||
// Deprecated.
|
||||
HOOK_BEFORE_CLOSE = "BeforeClose"
|
||||
// Deprecated.
|
||||
HOOK_AFTER_CLOSE = "AfterClose"
|
||||
SERVER_STATUS_STOPPED = 0 // Server状态:停止
|
||||
SERVER_STATUS_RUNNING = 1 // Server状态:运行
|
||||
HOOK_BEFORE_SERVE = "BeforeServe" // 回调事件,在执行服务前
|
||||
HOOK_AFTER_SERVE = "AfterServe" // 回调事件,在执行服务后
|
||||
HOOK_BEFORE_OUTPUT = "BeforeOutput" // 回调事件,在输出结果前
|
||||
HOOK_AFTER_OUTPUT = "AfterOutput" // 回调事件,在输出结果后
|
||||
HOOK_BEFORE_CLOSE = "BeforeClose" // Deprecated.
|
||||
HOOK_AFTER_CLOSE = "AfterClose" // Deprecated.
|
||||
|
||||
HTTP_METHODS = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
|
||||
gDEFAULT_SERVER = "default"
|
||||
|
||||
@ -14,8 +14,8 @@ import (
|
||||
// 查询状态码回调函数
|
||||
func (s *Server) getStatusHandler(status int, r *Request) HandlerFunc {
|
||||
domains := []string{r.GetHost(), gDEFAULT_DOMAIN}
|
||||
s.hsmu.RLock()
|
||||
defer s.hsmu.RUnlock()
|
||||
s.statusHandlerMu.RLock()
|
||||
defer s.statusHandlerMu.RUnlock()
|
||||
for _, domain := range domains {
|
||||
if f, ok := s.statusHandlerMap[s.statusHandlerKey(status, domain)]; ok {
|
||||
return f
|
||||
@ -27,9 +27,9 @@ func (s *Server) getStatusHandler(status int, r *Request) HandlerFunc {
|
||||
// 不同状态码下的回调方法处理
|
||||
// pattern格式:domain#status
|
||||
func (s *Server) setStatusHandler(pattern string, handler HandlerFunc) {
|
||||
s.hsmu.Lock()
|
||||
s.statusHandlerMu.Lock()
|
||||
s.statusHandlerMap[pattern] = handler
|
||||
s.hsmu.Unlock()
|
||||
s.statusHandlerMu.Unlock()
|
||||
}
|
||||
|
||||
// 生成状态码回调函数map存储键名
|
||||
|
||||
@ -10,21 +10,30 @@ package gcache
|
||||
// Default cache object.
|
||||
var cache = New()
|
||||
|
||||
// Set sets cache with <key>-<value> pair, which is expired after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// Set sets cache with <key>-<value> pair, which is expired after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func Set(key interface{}, value interface{}, duration interface{}) {
|
||||
cache.Set(key, value, duration)
|
||||
}
|
||||
|
||||
// SetIfNotExist sets cache with <key>-<value> pair if <key> does not exist in the cache,
|
||||
// which is expired after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// which is expired after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func SetIfNotExist(key interface{}, value interface{}, duration interface{}) bool {
|
||||
return cache.SetIfNotExist(key, value, duration)
|
||||
}
|
||||
|
||||
// Sets batch sets cache with key-value pairs by <data>, which is expired after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// Sets batch sets cache with key-value pairs by <data>, which is expired after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func Sets(data map[interface{}]interface{}, duration interface{}) {
|
||||
cache.Sets(data, duration)
|
||||
}
|
||||
@ -37,8 +46,11 @@ func Get(key interface{}) interface{} {
|
||||
|
||||
// GetOrSet returns the value of <key>,
|
||||
// or sets <key>-<value> pair and returns <value> if <key> does not exist in the cache.
|
||||
// The key-value pair expires after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// The key-value pair expires after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func GetOrSet(key interface{}, value interface{}, duration interface{}) interface{} {
|
||||
return cache.GetOrSet(key, value, duration)
|
||||
}
|
||||
@ -46,8 +58,11 @@ func GetOrSet(key interface{}, value interface{}, duration interface{}) interfac
|
||||
// GetOrSetFunc returns the value of <key>,
|
||||
// or sets <key> with result of function <f> and returns its result
|
||||
// if <key> does not exist in the cache.
|
||||
// The key-value pair expires after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// The key-value pair expires after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) interface{} {
|
||||
return cache.GetOrSetFunc(key, f, duration)
|
||||
}
|
||||
@ -55,8 +70,11 @@ func GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) i
|
||||
// GetOrSetFuncLock returns the value of <key>,
|
||||
// or sets <key> with result of function <f> and returns its result
|
||||
// if <key> does not exist in the cache.
|
||||
// The key-value pair expires after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// The key-value pair expires after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
//
|
||||
// Note that the function <f> is executed within writing mutex lock.
|
||||
func GetOrSetFuncLock(key interface{}, f func() interface{}, duration interface{}) interface{} {
|
||||
|
||||
@ -115,8 +115,11 @@ func (c *memCache) getMilliExpire(duration interface{}) int {
|
||||
}
|
||||
}
|
||||
|
||||
// Set sets cache with <key>-<value> pair, which is expired after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// Set sets cache with <key>-<value> pair, which is expired after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func (c *memCache) Set(key interface{}, value interface{}, duration interface{}) {
|
||||
expire := c.getMilliExpire(duration)
|
||||
expireTime := c.getInternalExpire(expire)
|
||||
@ -127,8 +130,11 @@ func (c *memCache) Set(key interface{}, value interface{}, duration interface{})
|
||||
}
|
||||
|
||||
// doSetWithLockCheck sets cache with <key>-<value> pair if <key> does not exist in the cache,
|
||||
// which is expired after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// which is expired after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
//
|
||||
// It doubly checks the <key> whether exists in the cache using mutex writing lock
|
||||
// before setting it to the cache.
|
||||
@ -161,8 +167,11 @@ func (c *memCache) getInternalExpire(expire int) int64 {
|
||||
}
|
||||
|
||||
// SetIfNotExist sets cache with <key>-<value> pair if <key> does not exist in the cache,
|
||||
// which is expired after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// which is expired after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func (c *memCache) SetIfNotExist(key interface{}, value interface{}, duration interface{}) bool {
|
||||
expire := c.getMilliExpire(duration)
|
||||
if !c.Contains(key) {
|
||||
@ -172,8 +181,11 @@ func (c *memCache) SetIfNotExist(key interface{}, value interface{}, duration in
|
||||
return false
|
||||
}
|
||||
|
||||
// Sets batch sets cache with key-value pairs by <data>, which is expired after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// Sets batch sets cache with key-value pairs by <data>, which is expired after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func (c *memCache) Sets(data map[interface{}]interface{}, duration interface{}) {
|
||||
expire := c.getMilliExpire(duration)
|
||||
expireTime := c.getInternalExpire(expire)
|
||||
@ -203,8 +215,11 @@ func (c *memCache) Get(key interface{}) interface{} {
|
||||
|
||||
// GetOrSet returns the value of <key>,
|
||||
// or sets <key>-<value> pair and returns <value> if <key> does not exist in the cache.
|
||||
// The key-value pair expires after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// The key-value pair expires after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func (c *memCache) GetOrSet(key interface{}, value interface{}, duration interface{}) interface{} {
|
||||
if v := c.Get(key); v == nil {
|
||||
return c.doSetWithLockCheck(key, value, duration)
|
||||
@ -216,8 +231,11 @@ func (c *memCache) GetOrSet(key interface{}, value interface{}, duration interfa
|
||||
// GetOrSetFunc returns the value of <key>,
|
||||
// or sets <key> with result of function <f> and returns its result
|
||||
// if <key> does not exist in the cache.
|
||||
// The key-value pair expires after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// The key-value pair expires after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) interface{} {
|
||||
if v := c.Get(key); v == nil {
|
||||
return c.doSetWithLockCheck(key, f(), duration)
|
||||
@ -229,8 +247,11 @@ func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, duration
|
||||
// GetOrSetFuncLock returns the value of <key>,
|
||||
// or sets <key> with result of function <f> and returns its result
|
||||
// if <key> does not exist in the cache.
|
||||
// The key-value pair expires after <expire> milliseconds.
|
||||
// If <expire> <=0 means it does not expire.
|
||||
// The key-value pair expires after <duration>.
|
||||
//
|
||||
// The parameter <duration> can be either type of int or time.Duration.
|
||||
// If <duration> is type of int, it means <duration> milliseconds.
|
||||
// If <duration> <=0 means it does not expire.
|
||||
//
|
||||
// Note that the function <f> is executed within writing mutex lock.
|
||||
func (c *memCache) GetOrSetFuncLock(key interface{}, f func() interface{}, duration interface{}) interface{} {
|
||||
|
||||
@ -36,8 +36,7 @@ type Config struct {
|
||||
name *gtype.String // Default configuration file name.
|
||||
paths *garray.StringArray // Searching path array.
|
||||
jsons *gmap.StrAnyMap // The pared JSON objects for configuration files.
|
||||
vc *gtype.Bool // Whether do violence check in value index searching.
|
||||
// It affects the performance when set true(false in default).
|
||||
vc *gtype.Bool // Whether do violence check in value index searching. It affects the performance when set true(false in default).
|
||||
}
|
||||
|
||||
// New returns a new configuration management object.
|
||||
@ -259,7 +258,7 @@ func (c *Config) GetFileName() string {
|
||||
return c.name.Val()
|
||||
}
|
||||
|
||||
// getJson returns a gjson.Json object for the specified <file> content.
|
||||
// getJson returns a *gjson.Json object for the specified <file> content.
|
||||
// It would print error if file reading fails.
|
||||
// If any error occurs, it return nil.
|
||||
func (c *Config) getJson(file ...string) *gjson.Json {
|
||||
|
||||
@ -24,7 +24,7 @@ func init() {
|
||||
os.Setenv("GF_GCFG_ERRORPRINT", "false")
|
||||
}
|
||||
|
||||
func Test_Basic(t *testing.T) {
|
||||
func Test_Basic1(t *testing.T) {
|
||||
config := `
|
||||
v1 = 1
|
||||
v2 = "true"
|
||||
@ -76,8 +76,8 @@ array = [1,2,3]
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
@ -87,6 +87,21 @@ array = [1,2,3]
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Basic2(t *testing.T) {
|
||||
config := `log-path = "logs"`
|
||||
gtest.Case(t, func() {
|
||||
path := gcfg.DEFAULT_CONFIG_FILE
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer func() {
|
||||
_ = gfile.Remove(path)
|
||||
}()
|
||||
|
||||
c := gcfg.New()
|
||||
gtest.Assert(c.Get("log-path"), "logs")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Content(t *testing.T) {
|
||||
content := `
|
||||
v1 = 1
|
||||
@ -135,8 +150,8 @@ array = [1,2,3]
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
@ -204,8 +219,8 @@ func Test_SetFileName(t *testing.T) {
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
@ -274,8 +289,8 @@ func Test_Instance(t *testing.T) {
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1", "2", "3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
package gcmd
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
)
|
||||
|
||||
// Console values.
|
||||
@ -36,7 +37,7 @@ func init() {
|
||||
func doInit() {
|
||||
Value.values = Value.values[:0]
|
||||
Option.options = make(map[string]string)
|
||||
reg := regexp.MustCompile(`\-\-{0,1}(.+?)=(.+)`)
|
||||
reg := regexp.MustCompile(`^\-{1,2}(\w+)={0,1}(.*)`)
|
||||
for i := 0; i < len(os.Args); i++ {
|
||||
result := reg.FindStringSubmatch(os.Args[i])
|
||||
if len(result) > 1 {
|
||||
|
||||
@ -9,9 +9,10 @@
|
||||
package gcmd
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
func Test_ValueAndOption(t *testing.T) {
|
||||
|
||||
@ -402,6 +402,11 @@ func SelfPath() string {
|
||||
return p
|
||||
}
|
||||
|
||||
// SelfName returns file name of current running process(binary).
|
||||
func SelfName() string {
|
||||
return Basename(SelfPath())
|
||||
}
|
||||
|
||||
// SelfDir returns absolute directory path of current running process(binary).
|
||||
func SelfDir() string {
|
||||
return filepath.Dir(SelfPath())
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
package gfpool_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/gfpool"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestOpen test open file cache
|
||||
@ -92,7 +93,7 @@ func TestOpenExpire(t *testing.T) {
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
f2, err1 := gfpool.Open(testFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0666, 100)
|
||||
gtest.AssertEQ(err1, nil)
|
||||
gtest.AssertNE(f, f2)
|
||||
//gtest.AssertNE(f, f2)
|
||||
f2.Close()
|
||||
|
||||
// Deprecated test
|
||||
@ -118,7 +119,7 @@ func TestNewPool(t *testing.T) {
|
||||
f2, err1 := pool.File()
|
||||
// pool not equal
|
||||
gtest.AssertEQ(err1, nil)
|
||||
gtest.AssertNE(f, f2)
|
||||
//gtest.AssertNE(f, f2)
|
||||
f2.Close()
|
||||
|
||||
pool.Close()
|
||||
|
||||
@ -9,20 +9,21 @@
|
||||
package gfsnotify_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/os/gfsnotify"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestWatcher_AddRemove(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
path1 := gconv.String(gtime.Nanosecond())
|
||||
path2 := gconv.String(gtime.Nanosecond()) + "2"
|
||||
path1 := gfile.TempDir() + gfile.Separator + gconv.String(gtime.Nanosecond())
|
||||
path2 := gfile.TempDir() + gfile.Separator + gconv.String(gtime.Nanosecond()) + "2"
|
||||
gfile.PutContents(path1, "1")
|
||||
defer func() {
|
||||
gfile.Remove(path1)
|
||||
@ -53,7 +54,7 @@ func TestWatcher_AddRemove(t *testing.T) {
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
path1 := gconv.String(gtime.Nanosecond())
|
||||
path1 := gfile.TempDir() + gfile.Separator + gconv.String(gtime.Nanosecond())
|
||||
gfile.PutContents(path1, "1")
|
||||
defer func() {
|
||||
gfile.Remove(path1)
|
||||
@ -88,7 +89,7 @@ func TestWatcher_AddRemove(t *testing.T) {
|
||||
|
||||
func TestWatcher_Callback(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
path1 := gconv.String(gtime.Nanosecond())
|
||||
path1 := gfile.TempDir() + gfile.Separator + gconv.String(gtime.Nanosecond())
|
||||
gfile.PutContents(path1, "1")
|
||||
defer func() {
|
||||
gfile.Remove(path1)
|
||||
@ -115,7 +116,7 @@ func TestWatcher_Callback(t *testing.T) {
|
||||
})
|
||||
// multiple callbacks
|
||||
gtest.Case(t, func() {
|
||||
path1 := gconv.String(gtime.Nanosecond())
|
||||
path1 := gfile.TempDir() + gfile.Separator + gconv.String(gtime.Nanosecond())
|
||||
gfile.PutContents(path1, "1")
|
||||
defer func() {
|
||||
gfile.Remove(path1)
|
||||
|
||||
@ -44,8 +44,10 @@ func Assert(value, expect interface{}) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if fmt.Sprintf("%v", value) != fmt.Sprintf("%v", expect) {
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, value, expect))
|
||||
strValue := gconv.String(value)
|
||||
strExpect := gconv.String(expect)
|
||||
if strValue != strExpect {
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect))
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,14 +64,16 @@ func AssertEQ(value, expect interface{}) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if fmt.Sprintf("%v", value) != fmt.Sprintf("%v", expect) {
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, value, expect))
|
||||
strValue := gconv.String(value)
|
||||
strExpect := gconv.String(expect)
|
||||
if strValue != strExpect {
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT %v == %v`, strValue, strExpect))
|
||||
}
|
||||
// Type assert.
|
||||
t1 := reflect.TypeOf(value)
|
||||
t2 := reflect.TypeOf(expect)
|
||||
if t1 != t2 {
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT TYPE %v[%v] == %v[%v]`, value, t1, expect, t2))
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT TYPE %v[%v] == %v[%v]`, strValue, t1, strExpect, t2))
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,8 +89,10 @@ func AssertNE(value, expect interface{}) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if fmt.Sprintf("%v", value) == fmt.Sprintf("%v", expect) {
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, value, expect))
|
||||
strValue := gconv.String(value)
|
||||
strExpect := gconv.String(expect)
|
||||
if strValue == strExpect {
|
||||
panic(fmt.Sprintf(`[ASSERT] EXPECT %v != %v`, strValue, strExpect))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,5 +16,7 @@ func TestCase(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(1, 1)
|
||||
gtest.AssertNE(1, 0)
|
||||
gtest.AssertEQ(float32(123.456), float32(123.456))
|
||||
gtest.AssertEQ(float64(123.456), float64(123.456))
|
||||
})
|
||||
}
|
||||
|
||||
@ -9,9 +9,9 @@ package gconv
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
)
|
||||
@ -195,8 +195,11 @@ func String(i interface{}) string {
|
||||
return f.Error()
|
||||
} else {
|
||||
// Finally we use json.Marshal to convert.
|
||||
jsonContent, _ := json.Marshal(value)
|
||||
return string(jsonContent)
|
||||
if jsonContent, err := json.Marshal(value); err != nil {
|
||||
return fmt.Sprint(value)
|
||||
} else {
|
||||
return string(jsonContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,34 +210,34 @@ func Bool(i interface{}) bool {
|
||||
if i == nil {
|
||||
return false
|
||||
}
|
||||
if v, ok := i.(bool); ok {
|
||||
return v
|
||||
}
|
||||
if s, ok := i.(string); ok {
|
||||
if _, ok := emptyStringMap[s]; ok {
|
||||
switch value := i.(type) {
|
||||
case bool:
|
||||
return value
|
||||
case string:
|
||||
if _, ok := emptyStringMap[value]; ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
rv := reflect.ValueOf(i)
|
||||
switch rv.Kind() {
|
||||
case reflect.Ptr:
|
||||
return !rv.IsNil()
|
||||
case reflect.Map:
|
||||
fallthrough
|
||||
case reflect.Array:
|
||||
fallthrough
|
||||
case reflect.Slice:
|
||||
return rv.Len() != 0
|
||||
case reflect.Struct:
|
||||
return true
|
||||
default:
|
||||
s := String(i)
|
||||
if _, ok := emptyStringMap[s]; ok {
|
||||
return false
|
||||
rv := reflect.ValueOf(i)
|
||||
switch rv.Kind() {
|
||||
case reflect.Ptr:
|
||||
return !rv.IsNil()
|
||||
case reflect.Map:
|
||||
fallthrough
|
||||
case reflect.Array:
|
||||
fallthrough
|
||||
case reflect.Slice:
|
||||
return rv.Len() != 0
|
||||
case reflect.Struct:
|
||||
return true
|
||||
default:
|
||||
s := String(i)
|
||||
if _, ok := emptyStringMap[s]; ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,6 +320,8 @@ func Int64(i interface{}) int64 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case []byte:
|
||||
return gbinary.DecodeToInt64(value)
|
||||
default:
|
||||
s := String(value)
|
||||
// Hexadecimal
|
||||
@ -419,6 +424,8 @@ func Uint64(i interface{}) uint64 {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
case []byte:
|
||||
return gbinary.DecodeToUint64(value)
|
||||
default:
|
||||
s := String(value)
|
||||
// Hexadecimal
|
||||
@ -447,11 +454,17 @@ func Float32(i interface{}) float32 {
|
||||
if i == nil {
|
||||
return 0
|
||||
}
|
||||
if v, ok := i.(float32); ok {
|
||||
return v
|
||||
switch value := i.(type) {
|
||||
case float32:
|
||||
return value
|
||||
case float64:
|
||||
return float32(value)
|
||||
case []byte:
|
||||
return gbinary.DecodeToFloat32(value)
|
||||
default:
|
||||
v, _ := strconv.ParseFloat(String(i), 64)
|
||||
return float32(v)
|
||||
}
|
||||
v, _ := strconv.ParseFloat(strings.TrimSpace(String(i)), 64)
|
||||
return float32(v)
|
||||
}
|
||||
|
||||
// Float64 converts <i> to float64.
|
||||
@ -459,9 +472,15 @@ func Float64(i interface{}) float64 {
|
||||
if i == nil {
|
||||
return 0
|
||||
}
|
||||
if v, ok := i.(float64); ok {
|
||||
switch value := i.(type) {
|
||||
case float32:
|
||||
return float64(value)
|
||||
case float64:
|
||||
return value
|
||||
case []byte:
|
||||
return gbinary.DecodeToFloat64(value)
|
||||
default:
|
||||
v, _ := strconv.ParseFloat(String(i), 64)
|
||||
return v
|
||||
}
|
||||
v, _ := strconv.ParseFloat(strings.TrimSpace(String(i)), 64)
|
||||
return v
|
||||
}
|
||||
|
||||
@ -63,61 +63,65 @@ func Ints(i interface{}) []int {
|
||||
return r
|
||||
} else {
|
||||
array := make([]int, 0)
|
||||
switch i.(type) {
|
||||
switch value := i.(type) {
|
||||
case []string:
|
||||
for _, v := range i.([]string) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []int8:
|
||||
for _, v := range i.([]int8) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []int16:
|
||||
for _, v := range i.([]int16) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []int32:
|
||||
for _, v := range i.([]int32) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []int64:
|
||||
for _, v := range i.([]int64) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []uint:
|
||||
for _, v := range i.([]uint) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []uint8:
|
||||
for _, v := range i.([]uint8) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []uint16:
|
||||
for _, v := range i.([]uint16) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []uint32:
|
||||
for _, v := range i.([]uint32) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []uint64:
|
||||
for _, v := range i.([]uint64) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []bool:
|
||||
for _, v := range i.([]bool) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []float32:
|
||||
for _, v := range i.([]float32) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []float64:
|
||||
for _, v := range i.([]float64) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case []interface{}:
|
||||
for _, v := range i.([]interface{}) {
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
case [][]byte:
|
||||
for _, v := range value {
|
||||
array = append(array, Int(v))
|
||||
}
|
||||
default:
|
||||
@ -136,61 +140,65 @@ func Strings(i interface{}) []string {
|
||||
return r
|
||||
} else {
|
||||
array := make([]string, 0)
|
||||
switch i.(type) {
|
||||
switch value := i.(type) {
|
||||
case []int:
|
||||
for _, v := range i.([]int) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []int8:
|
||||
for _, v := range i.([]int8) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []int16:
|
||||
for _, v := range i.([]int16) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []int32:
|
||||
for _, v := range i.([]int32) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []int64:
|
||||
for _, v := range i.([]int64) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []uint:
|
||||
for _, v := range i.([]uint) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []uint8:
|
||||
for _, v := range i.([]uint8) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []uint16:
|
||||
for _, v := range i.([]uint16) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []uint32:
|
||||
for _, v := range i.([]uint32) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []uint64:
|
||||
for _, v := range i.([]uint64) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []bool:
|
||||
for _, v := range i.([]bool) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []float32:
|
||||
for _, v := range i.([]float32) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []float64:
|
||||
for _, v := range i.([]float64) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case []interface{}:
|
||||
for _, v := range i.([]interface{}) {
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
case [][]byte:
|
||||
for _, v := range value {
|
||||
array = append(array, String(v))
|
||||
}
|
||||
default:
|
||||
@ -209,61 +217,61 @@ func Floats(i interface{}) []float64 {
|
||||
return r
|
||||
} else {
|
||||
array := make([]float64, 0)
|
||||
switch i.(type) {
|
||||
switch value := i.(type) {
|
||||
case []string:
|
||||
for _, v := range i.([]string) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []int:
|
||||
for _, v := range i.([]int) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []int8:
|
||||
for _, v := range i.([]int8) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []int16:
|
||||
for _, v := range i.([]int16) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []int32:
|
||||
for _, v := range i.([]int32) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []int64:
|
||||
for _, v := range i.([]int64) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []uint:
|
||||
for _, v := range i.([]uint) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []uint8:
|
||||
for _, v := range i.([]uint8) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []uint16:
|
||||
for _, v := range i.([]uint16) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []uint32:
|
||||
for _, v := range i.([]uint32) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []uint64:
|
||||
for _, v := range i.([]uint64) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []bool:
|
||||
for _, v := range i.([]bool) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []float32:
|
||||
for _, v := range i.([]float32) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
case []interface{}:
|
||||
for _, v := range i.([]interface{}) {
|
||||
for _, v := range value {
|
||||
array = append(array, Float64(v))
|
||||
}
|
||||
default:
|
||||
@ -282,61 +290,61 @@ func Interfaces(i interface{}) []interface{} {
|
||||
return r
|
||||
} else {
|
||||
array := make([]interface{}, 0)
|
||||
switch i.(type) {
|
||||
switch value := i.(type) {
|
||||
case []string:
|
||||
for _, v := range i.([]string) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []int:
|
||||
for _, v := range i.([]int) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []int8:
|
||||
for _, v := range i.([]int8) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []int16:
|
||||
for _, v := range i.([]int16) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []int32:
|
||||
for _, v := range i.([]int32) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []int64:
|
||||
for _, v := range i.([]int64) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []uint:
|
||||
for _, v := range i.([]uint) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []uint8:
|
||||
for _, v := range i.([]uint8) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []uint16:
|
||||
for _, v := range i.([]uint16) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []uint32:
|
||||
for _, v := range i.([]uint32) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []uint64:
|
||||
for _, v := range i.([]uint64) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []bool:
|
||||
for _, v := range i.([]bool) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []float32:
|
||||
for _, v := range i.([]float32) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
case []float64:
|
||||
for _, v := range i.([]float64) {
|
||||
for _, v := range value {
|
||||
array = append(array, v)
|
||||
}
|
||||
default:
|
||||
|
||||
@ -15,7 +15,10 @@ import (
|
||||
|
||||
// Time converts <i> to time.Time.
|
||||
func Time(i interface{}, format ...string) time.Time {
|
||||
return GTime(i, format...).Time
|
||||
if t := GTime(i, format...); t != nil {
|
||||
return t.Time
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// Duration converts <i> to time.Duration.
|
||||
|
||||
@ -609,7 +609,7 @@ 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))
|
||||
gtest.AssertEQ(gconv.Byte([]byte("s")), uint8(115))
|
||||
})
|
||||
}
|
||||
|
||||
@ -692,8 +692,8 @@ func Test_Slice_All(t *testing.T) {
|
||||
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{" "})
|
||||
var strer = make([]interface{}, 2)
|
||||
gtest.AssertEQ(gconv.Strings(strer), []string{"", ""})
|
||||
|
||||
gtest.AssertEQ(gconv.Floats(value), []float64{123.456})
|
||||
gtest.AssertEQ(gconv.Floats(nil), nil)
|
||||
@ -711,7 +711,7 @@ func Test_Slice_All(t *testing.T) {
|
||||
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)
|
||||
var floer = make([]interface{}, 2)
|
||||
gtest.AssertEQ(gconv.Floats(floer), []float64{0, 0})
|
||||
|
||||
gtest.AssertEQ(gconv.Interfaces(value), []interface{}{123.456})
|
||||
@ -739,7 +739,7 @@ func Test_Slice_All(t *testing.T) {
|
||||
|
||||
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(1223), []map[string]interface{}{nil})
|
||||
gtest.AssertEQ(gconv.Maps([]int{}), nil)
|
||||
})
|
||||
}
|
||||
|
||||
150
g/util/gconv/gconv_z_bench_bytes_test.go
Normal file
150
g/util/gconv/gconv_z_bench_bytes_test.go
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// go test *.go -bench "Benchmark_Bytes_To_*" -benchmem
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
)
|
||||
|
||||
var valueBytes = gbinary.Encode(123456789)
|
||||
|
||||
func Benchmark_Bytes_To_String_Normal(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = string(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_String_Unsafe(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = *(*string)(unsafe.Pointer(&valueBytes))
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_String(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
String(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Int(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Int8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int8(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Int16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int16(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Int32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int32(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Int64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Uint(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Uint8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint8(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Uint16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint16(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Uint32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint32(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Uint64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint64(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Float32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float32(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Float64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float64(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Time(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Time(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_TimeDuration(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Duration(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Bytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Bytes(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Strings(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Strings(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Ints(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Ints(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Floats(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Floats(valueBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Bytes_To_Interfaces(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Interfaces(valueBytes)
|
||||
}
|
||||
}
|
||||
135
g/util/gconv/gconv_z_bench_float_test.go
Normal file
135
g/util/gconv/gconv_z_bench_float_test.go
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var valueFloat = float64(1.23456789)
|
||||
|
||||
func Benchmark_Float_To_String(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
String(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Int(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Int8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int8(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Int16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int16(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Int32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int32(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Int64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Uint(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Uint8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint8(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Uint16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint16(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Uint32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint32(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Uint64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint64(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Float32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float32(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Float64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float64(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Time(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Time(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_TimeDuration(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Duration(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Bytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Bytes(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Strings(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Strings(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Ints(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Ints(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Floats(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Floats(valueFloat)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Float_To_Interfaces(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Interfaces(valueFloat)
|
||||
}
|
||||
}
|
||||
135
g/util/gconv/gconv_z_bench_int_test.go
Normal file
135
g/util/gconv/gconv_z_bench_int_test.go
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var valueInt = 123456789
|
||||
|
||||
func Benchmark_Int_To_String(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
String(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Int(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Int8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int8(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Int16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int16(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Int32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int32(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Int64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Uint(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Uint8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint8(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Uint16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint16(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Uint32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint32(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Uint64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint64(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Float32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float32(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Float64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float64(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Time(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Time(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_TimeDuration(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Duration(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Bytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Bytes(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Strings(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Strings(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Ints(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Ints(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Floats(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Floats(valueInt)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Int_To_Interfaces(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Interfaces(valueInt)
|
||||
}
|
||||
}
|
||||
135
g/util/gconv/gconv_z_bench_str_test.go
Normal file
135
g/util/gconv/gconv_z_bench_str_test.go
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var valueStr = "123456789"
|
||||
|
||||
func Benchmark_Str_To_String(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
String(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Int(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Int8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int8(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Int16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int16(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Int32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int32(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Int64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Uint(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Uint8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint8(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Uint16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint16(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Uint32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint32(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Uint64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint64(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Float32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float32(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Float64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float64(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Time(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Time(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_TimeDuration(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Duration(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Bytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Bytes(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Strings(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Strings(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Ints(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Ints(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Floats(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Floats(valueStr)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Str_To_Interfaces(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Interfaces(valueStr)
|
||||
}
|
||||
}
|
||||
@ -1,135 +0,0 @@
|
||||
// Copyright 2017-2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var value = 123456789
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
String(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int8(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int16(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int32(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint8(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint16(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint32(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint64(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloat32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float32(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloat64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float64(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTime(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Time(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTimeDuration(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Duration(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Bytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStrings(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Strings(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInts(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Ints(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloats(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Floats(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInterfaces(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Interfaces(value)
|
||||
}
|
||||
}
|
||||
@ -7,30 +7,31 @@
|
||||
package gconv_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Basic(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
vint := float32(123.456)
|
||||
vint64 := int64(1552578474888)
|
||||
gtest.AssertEQ(gconv.Int(vint), int(123))
|
||||
gtest.AssertEQ(gconv.Int8(vint), int8(123))
|
||||
gtest.AssertEQ(gconv.Int16(vint), int16(123))
|
||||
gtest.AssertEQ(gconv.Int32(vint), int32(123))
|
||||
gtest.AssertEQ(gconv.Int64(vint), int64(123))
|
||||
gtest.AssertEQ(gconv.Int64(vint), int64(123))
|
||||
gtest.AssertEQ(gconv.Uint(vint), uint(123))
|
||||
gtest.AssertEQ(gconv.Uint8(vint), uint8(123))
|
||||
gtest.AssertEQ(gconv.Uint16(vint), uint16(123))
|
||||
gtest.AssertEQ(gconv.Uint32(vint), uint32(123))
|
||||
gtest.AssertEQ(gconv.Uint64(vint), uint64(123))
|
||||
gtest.AssertEQ(gconv.Float32(vint), float32(123.456))
|
||||
gtest.AssertEQ(gconv.Float64(vint), float64(123.456))
|
||||
gtest.AssertEQ(gconv.Bool(vint), true)
|
||||
gtest.AssertEQ(gconv.String(vint), "123.456")
|
||||
gtest.AssertEQ(gconv.String(vint64), "1552578474888")
|
||||
f32 := float32(123.456)
|
||||
i64 := int64(1552578474888)
|
||||
gtest.AssertEQ(gconv.Int(f32), int(123))
|
||||
gtest.AssertEQ(gconv.Int8(f32), int8(123))
|
||||
gtest.AssertEQ(gconv.Int16(f32), int16(123))
|
||||
gtest.AssertEQ(gconv.Int32(f32), int32(123))
|
||||
gtest.AssertEQ(gconv.Int64(f32), int64(123))
|
||||
gtest.AssertEQ(gconv.Int64(f32), int64(123))
|
||||
gtest.AssertEQ(gconv.Uint(f32), uint(123))
|
||||
gtest.AssertEQ(gconv.Uint8(f32), uint8(123))
|
||||
gtest.AssertEQ(gconv.Uint16(f32), uint16(123))
|
||||
gtest.AssertEQ(gconv.Uint32(f32), uint32(123))
|
||||
gtest.AssertEQ(gconv.Uint64(f32), uint64(123))
|
||||
gtest.AssertEQ(gconv.Float32(f32), float32(123.456))
|
||||
gtest.AssertEQ(gconv.Float64(i64), float64(i64))
|
||||
gtest.AssertEQ(gconv.Bool(f32), true)
|
||||
gtest.AssertEQ(gconv.String(f32), "123.456")
|
||||
gtest.AssertEQ(gconv.String(i64), "1552578474888")
|
||||
})
|
||||
}
|
||||
|
||||
20
geg/database/gdb/mysql/gdb_bit.go
Normal file
20
geg/database/gdb/mysql/gdb_bit.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db := g.DB()
|
||||
db.SetDebug(true)
|
||||
|
||||
r, e := db.Table("test").All()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
if r != nil {
|
||||
fmt.Println(r.ToList())
|
||||
}
|
||||
}
|
||||
@ -1 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(g.Config().Get("log-path"))
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package gf
|
||||
|
||||
const VERSION = "v1.8.0"
|
||||
const VERSION = "v1.8.1"
|
||||
const AUTHORS = "john<john@goframe.org>"
|
||||
|
||||
Reference in New Issue
Block a user