fix issue in gtime convert in package gconv; add Structs/Scan functions for gdb.Model; add GetStructs/GetScan functions for gdb.Base and gdb.TX

This commit is contained in:
John 2019-03-07 23:36:45 +08:00
parent 5d874e9063
commit 2ba59e8943
13 changed files with 729 additions and 120 deletions

View File

@ -47,7 +47,9 @@ type DB interface {
GetOne(query string, args ...interface{}) (Record, error)
GetValue(query string, args ...interface{}) (Value, error)
GetCount(query string, args ...interface{}) (int, error)
GetStruct(obj interface{}, query string, args ...interface{}) error
GetStruct(objPointer interface{}, query string, args ...interface{}) error
GetStructs(objPointerSlice interface{}, query string, args ...interface{}) error
GetScan(objPointer interface{}, query string, args ...interface{}) error
// 创建底层数据库master/slave链接对象
Master() (*sql.DB, error)

View File

@ -165,13 +165,44 @@ func (bs *dbBase) GetOne(query string, args ...interface{}) (Record, error) {
return nil, nil
}
// 数据库查询,获取查询结果记录自动映射数据到给定的struct对象中
func (bs *dbBase) GetStruct(obj interface{}, query string, args ...interface{}) error {
// 数据库查询,查询单条记录自动映射数据到给定的struct对象中
func (bs *dbBase) GetStruct(objPointer interface{}, query string, args ...interface{}) error {
one, err := bs.GetOne(query, args...)
if err != nil {
return err
}
return one.ToStruct(obj)
return one.ToStruct(objPointer)
}
// 数据库查询查询多条记录并自动转换为指定的slice对象, 如: []struct/[]*struct。
func (bs *dbBase) GetStructs(objPointerSlice interface{}, query string, args ...interface{}) error {
all, err := bs.GetAll(query, args...)
if err != nil {
return err
}
return all.ToStructs(objPointerSlice)
}
// 将结果转换为指定的struct/*struct/[]struct/[]*struct,
// 参数应该为指针类型,否则返回失败。
// 该方法自动识别参数类型调用Struct/Structs方法。
func (bs *dbBase) GetScan(objPointer interface{}, query string, args ...interface{}) error {
t := reflect.TypeOf(objPointer)
k := t.Kind()
if k != reflect.Ptr {
return fmt.Errorf("params should be type of pointer, but got: %v", k)
}
k = t.Elem().Kind()
switch k {
case reflect.Array:
case reflect.Slice:
return bs.db.GetStructs(objPointer, query, args ...)
case reflect.Struct:
return bs.db.GetStruct(objPointer, query, args ...)
default:
return fmt.Errorf("element type should be type of struct/slice, unsupported: %v", k)
}
return nil
}
// 数据库查询,获取查询字段值

View File

@ -438,13 +438,44 @@ func (md *Model) Value() (Value, error) {
return nil, nil
}
// 链式操作查询单条记录并自动转换为struct对象
func (md *Model) Struct(obj interface{}) error {
// 链式操作查询单条记录并自动转换为struct对象, 参数必须为对象的指针,不能为空指针。
func (md *Model) Struct(objPointer interface{}) error {
one, err := md.One()
if err != nil {
return err
}
return one.ToStruct(obj)
return one.ToStruct(objPointer)
}
// 链式操作查询多条记录并自动转换为指定的slice对象, 如: []struct/[]*struct。
func (md *Model) Structs(objPointerSlice interface{}) error {
r, err := md.All()
if err != nil {
return err
}
return r.ToStructs(objPointerSlice)
}
// 链式操作将结果转换为指定的struct/*struct/[]struct/[]*struct,
// 参数应该为指针类型,否则返回失败。
// 该方法自动识别参数类型调用Struct/Structs方法。
func (md *Model) Scan(objPointer interface{}) error {
t := reflect.TypeOf(objPointer)
k := t.Kind()
if k != reflect.Ptr {
return fmt.Errorf("params should be type of pointer, but got: %v", k)
}
k = t.Elem().Kind()
switch k {
case reflect.Array:
case reflect.Slice:
return md.Structs(objPointer)
case reflect.Struct:
return md.Struct(objPointer)
default:
return fmt.Errorf("element type should be type of struct/slice, unsupported: %v", k)
}
return nil
}
// 链式操作查询数量fields可以为空也可以自定义查询字段

View File

@ -8,8 +8,10 @@ package gdb
import (
"database/sql"
"fmt"
"github.com/gogf/gf/g/text/gregex"
_ "github.com/gogf/gf/third/github.com/go-sql-driver/mysql"
"reflect"
)
// 数据库事务对象
@ -75,6 +77,37 @@ func (tx *TX) GetStruct(obj interface{}, query string, args ...interface{}) erro
return one.ToStruct(obj)
}
// 数据库查询查询多条记录并自动转换为指定的slice对象, 如: []struct/[]*struct。
func (tx *TX) GetStructs(objPointerSlice interface{}, query string, args ...interface{}) error {
all, err := tx.GetAll(query, args...)
if err != nil {
return err
}
return all.ToStructs(objPointerSlice)
}
// 将结果转换为指定的struct/*struct/[]struct/[]*struct,
// 参数应该为指针类型,否则返回失败。
// 该方法自动识别参数类型调用Struct/Structs方法。
func (tx *TX) GetScan(objPointer interface{}, query string, args ...interface{}) error {
t := reflect.TypeOf(objPointer)
k := t.Kind()
if k != reflect.Ptr {
return fmt.Errorf("params should be type of pointer, but got: %v", k)
}
k = t.Elem().Kind()
switch k {
case reflect.Array:
case reflect.Slice:
return tx.db.GetStructs(objPointer, query, args ...)
case reflect.Struct:
return tx.db.GetStruct(objPointer, query, args ...)
default:
return fmt.Errorf("element type should be type of struct/slice, unsupported: %v", k)
}
return nil
}
// 数据库查询,获取查询字段值
func (tx *TX) GetValue(query string, args ...interface{}) (Value, error) {
one, err := tx.GetOne(query, args ...)

View File

@ -33,10 +33,6 @@ func (r Record) ToMap() Map {
}
// 将Map变量映射到指定的struct对象中注意参数应当是一个对象的指针
func (r Record) ToStruct(obj interface{}) error {
m := make(map[string]interface{})
for k, v := range r {
m[k] = v.Val()
}
return gconv.Struct(m, obj)
func (r Record) ToStruct(objPointer interface{}) error {
return gconv.Struct(r.ToMap(), objPointer)
}

View File

@ -7,7 +7,9 @@
package gdb
import (
"fmt"
"github.com/gogf/gf/g/encoding/gparser"
"reflect"
)
// 将结果集转换为JSON字符串
@ -96,3 +98,30 @@ func (r Result) ToUintRecord(key string) map[uint]Record {
}
return m
}
// 将结果列表转换为指定对象的slice。
func (r Result) ToStructs(objPointerSlice interface{}) error {
l := len(r)
if l == 0 {
return nil
}
t := reflect.TypeOf(objPointerSlice)
if t.Kind() != reflect.Ptr {
return fmt.Errorf("params should be type of pointer, but got: %v", t.Kind())
}
a := reflect.MakeSlice(t.Elem(), l, l)
itemType := a.Index(0).Type()
for i := 0; i < l; i++ {
if itemType.Kind() == reflect.Ptr {
e := reflect.New(itemType.Elem()).Elem()
r[i].ToStruct(e)
a.Index(i).Set(e.Addr())
} else {
e := reflect.New(itemType).Elem()
r[i].ToStruct(e)
a.Index(i).Set(e)
}
}
reflect.ValueOf(objPointerSlice).Elem().Set(a)
return nil
}

View File

@ -266,19 +266,159 @@ func TestDbBase_GetCount(t *testing.T) {
}
func TestDbBase_GetStruct(t *testing.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
if err := db.GetStruct(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
} else {
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
}
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
if err := db.GetStruct(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
} else {
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
}
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
if err := db.GetStruct(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
} else {
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
}
})
}
func TestDbBase_GetStructs(t *testing.T) {
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
if err := db.GetStructs(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []User
if err := db.GetStructs(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
})
}
func TestDbBase_GetScan(t *testing.T) {
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
if err := db.GetScan(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
} else {
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
}
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
if err := db.GetScan(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
} else {
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
}
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
if err := db.GetScan(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []User
if err := db.GetScan(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
})
}
func TestDbBase_Delete(t *testing.T) {

View File

@ -121,7 +121,7 @@ func TestModel_Replace(t *testing.T) {
"passport" : "t11",
"password" : "25d55ad283aa400af464c76d713c07ad",
"nickname" : "T11",
"create_time" : gtime.Now().String(),
"create_time" : "2018-10-10 00:01:10",
}).Replace()
if err != nil {
gtest.Fatal(err)
@ -136,7 +136,7 @@ func TestModel_Save(t *testing.T) {
"passport" : "t111",
"password" : "25d55ad283aa400af464c76d713c07ad",
"nickname" : "T111",
"create_time" : gtime.Now().String(),
"create_time" : "2018-10-10 00:01:10",
}).Save()
if err != nil {
gtest.Fatal(err)
@ -222,19 +222,164 @@ func TestModel_Select(t *testing.T) {
}
func TestModel_Struct(t *testing.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
err := db.Table("user").Where("id=1").Struct(user)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T111")
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
err := db.Table("user").Where("id=1").Struct(user)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T111")
gtest.Assert(user.CreateTime.String(), "2018-10-10 00:01:10")
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
err := db.Table("user").Where("id=1").Struct(user)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T111")
gtest.Assert(user.CreateTime.String(), "2018-10-10 00:01:10")
})
}
func TestModel_Structs(t *testing.T) {
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
err := db.Table("user").OrderBy("id asc").Structs(&users)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[0].CreateTime.String(), "2018-10-10 00:01:10")
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []*User
err := db.Table("user").OrderBy("id asc").Structs(&users)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[0].CreateTime.String(), "2018-10-10 00:01:10")
})
}
func TestModel_Scan(t *testing.T) {
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
err := db.Table("user").Where("id=1").Scan(user)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T111")
gtest.Assert(user.CreateTime.String(), "2018-10-10 00:01:10")
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
err := db.Table("user").Where("id=1").Scan(user)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T111")
gtest.Assert(user.CreateTime.String(), "2018-10-10 00:01:10")
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
err := db.Table("user").OrderBy("id asc").Scan(&users)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[0].CreateTime.String(), "2018-10-10 00:01:10")
})
gtest.Case(t, func() {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []*User
err := db.Table("user").OrderBy("id asc").Scan(&users)
if err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 3)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T111")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[0].CreateTime.String(), "2018-10-10 00:01:10")
})
}
func TestModel_OrderBy(t *testing.T) {

View File

@ -267,6 +267,29 @@ func TestTX_Save(t *testing.T) {
}
}
func TestTX_Update(t *testing.T) {
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
if result, err := db.Update("user", "create_time='2010-10-10 00:00:01'", "id=3"); err != nil {
gtest.Fatal(err)
} else {
n, _ := result.RowsAffected()
gtest.Assert(n, 1)
}
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
if value, err := db.Table("user").Fields("create_time").Where("id", 3).Value(); err != nil {
gtest.Fatal(err)
} else {
gtest.Assert(value.String(), "2010-10-10 00:00:01")
}
})
}
func TestTX_GetAll(t *testing.T) {
tx, err := db.Begin()
if err != nil {
@ -331,26 +354,215 @@ func TestTX_GetCount(t *testing.T) {
}
func TestTX_GetStruct(t *testing.T) {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
if err := tx.GetStruct(user, "SELECT * FROM user WHERE id=?", 1); err != nil {
gtest.Fatal(err)
} else {
gtest.Assert(user.NickName, "T11")
}
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
if err := tx.GetStruct(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T3")
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
if err := tx.GetStruct(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T3")
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
}
func TestTX_GetStructs(t *testing.T) {
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
if err := tx.GetStructs(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 4)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T11")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []User
if err := tx.GetStructs(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 4)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T11")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
}
func TestTX_GetScan(t *testing.T) {
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
if err := tx.GetScan(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T3")
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
if err := tx.GetScan(user, "SELECT * FROM user WHERE id=?", 3); err != nil {
gtest.Fatal(err)
}
gtest.Assert(user.NickName, "T3")
gtest.Assert(user.CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
if err := tx.GetScan(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 4)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T11")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
gtest.Case(t, func() {
tx, err := db.Begin()
if err != nil {
gtest.Fatal(err)
}
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []User
if err := tx.GetScan(&users, "SELECT * FROM user WHERE id>=?", 1); err != nil {
gtest.Fatal(err)
}
gtest.Assert(len(users), 4)
gtest.Assert(users[0].Id, 1)
gtest.Assert(users[1].Id, 2)
gtest.Assert(users[2].Id, 3)
gtest.Assert(users[0].NickName, "T11")
gtest.Assert(users[1].NickName, "T2")
gtest.Assert(users[2].NickName, "T3")
gtest.Assert(users[2].CreateTime.String(), "2010-10-10 00:00:01")
if err := tx.Commit(); err != nil {
gtest.Fatal(err)
}
})
}
func TestTX_Delete(t *testing.T) {

View File

@ -47,7 +47,16 @@ func Convert(i interface{}, t string, extraParams...interface{}) interface{} {
return Time(i, String(extraParams[0]))
}
return Time(i)
case "gtime.Time":
if len(extraParams) > 0 {
return GTime(i, String(extraParams[0]))
}
return *GTime(i)
case "*gtime.Time":
if len(extraParams) > 0 {
return GTime(i, String(extraParams[0]))
}
return GTime(i)
case "time.Duration": return TimeDuration(i)
default:
return i

View File

@ -15,68 +15,60 @@ import (
"strings"
)
// 将params键值对参数映射到对应的struct对象属性上第三个参数mapping为非必需表示自定义名称与属性名称的映射关系。
// 将params键值对参数映射到对应的struct对象属性上
// 第三个参数mapping为非必需表示自定义名称与属性名称的映射关系。
// 需要注意:
// 1、第二个参数应当为struct对象指针
// 2、struct对象的**公开属性(首字母大写)**才能被映射赋值;
// 3、map中的键名可以为小写映射转换时会自动将键名首字母转为大写做匹配映射如果无法匹配则忽略
func Struct(params interface{}, objPointer interface{}, attrMapping...map[string]string) error {
if params == nil {
return nil
return errors.New("params cannot be nil")
}
isParamMap := true
paramsMap := (map[string]interface{})(nil)
// 先将参数转为 map[string]interface{} 类型
if m, ok := params.(map[string]interface{}); ok {
paramsMap = m
} else {
paramsMap = make(map[string]interface{})
if reflect.ValueOf(params).Kind() == reflect.Map {
ks := reflect.ValueOf(params).MapKeys()
vs := reflect.ValueOf(params)
for _, k := range ks {
paramsMap[String(k.Interface())] = vs.MapIndex(k).Interface()
}
} else {
isParamMap = false
}
if objPointer == nil {
return errors.New("object pointer cannot be nil")
}
paramsMap := Map(params)
if paramsMap == nil {
return fmt.Errorf("invalid params: %v", params)
}
// struct的反射对象
elem := reflect.Value{}
if v, ok := objPointer.(reflect.Value); ok {
elem = v
} else {
elem = reflect.ValueOf(objPointer).Elem()
}
// 如果给定的参数不是map类型那么直接将参数值映射到第一个属性上
if !isParamMap {
if err := bindVarToStructByIndex(elem, 0, params); err != nil {
return err
rv := reflect.ValueOf(objPointer)
if kind := rv.Kind(); kind != reflect.Ptr {
return fmt.Errorf("object pointer should be type of: %v", kind)
}
return nil
if !rv.IsValid() || rv.IsNil() {
return errors.New("object pointer cannot be nil")
}
elem = rv.Elem()
}
// 已执行过转换的属性,只执行一次转换
dmap := make(map[string]bool)
// 已执行过转换的属性,只执行一次转换。
// 或者是已经执行过转换检查的属性(即使不进行转换), 以便重复判断。
doneMap := make(map[string]bool)
// 首先按照传递的映射关系进行匹配
if len(attrMapping) > 0 && len(attrMapping[0]) > 0 {
for mappingk, mappingv := range attrMapping[0] {
if v, ok := paramsMap[mappingk]; ok {
dmap[mappingv] = true
if err := bindVarToStructAttr(elem, mappingv, v); err != nil {
for mapK, mapV := range attrMapping[0] {
if v, ok := paramsMap[mapK]; ok {
doneMap[mapV] = true
if err := bindVarToStructAttr(elem, mapV, v); err != nil {
return err
}
}
}
}
// 其次匹配对象定义时绑定的属性名称
// 其次匹配对象定义时绑定的属性名称,
// 标签映射关系map如果有的话
tagmap := getTagMapOfStruct(objPointer)
for tagk, tagv := range tagmap {
if _, ok := dmap[tagv]; ok {
tagMap := getTagMapOfStruct(objPointer)
for tagk, tagv := range tagMap {
if _, ok := doneMap[tagv]; ok {
continue
}
if v, ok := paramsMap[tagk]; ok {
dmap[tagv] = true
doneMap[tagv] = true
if err := bindVarToStructAttr(elem, tagv, v); err != nil {
return err
}
@ -88,19 +80,19 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
for i := 0; i < elem.NumField(); i++ {
attrMap[elemType.Field(i).Name] = struct{}{}
}
for mapk, mapv := range paramsMap {
for mapK, mapV := range paramsMap {
name := ""
for _, checkName := range []string {
gstr.UcFirst(mapk),
gstr.ReplaceByMap(mapk, map[string]string{
gstr.UcFirst(mapK),
gstr.ReplaceByMap(mapK, map[string]string{
"_" : "",
"-" : "",
" " : "",
})} {
if _, ok := dmap[checkName]; ok {
})} {
if _, ok := doneMap[checkName]; ok {
continue
}
if _, ok := tagmap[checkName]; ok {
if _, ok := tagMap[checkName]; ok {
continue
}
// 循环查找属性名称进行匹配
@ -114,6 +106,7 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
break
}
}
doneMap[checkName] = true
if name != "" {
break
}
@ -122,7 +115,7 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
if name == "" {
continue
}
if err := bindVarToStructAttr(elem, name, mapv); err != nil {
if err := bindVarToStructAttr(elem, name, mapV); err != nil {
return err
}
}

View File

@ -22,7 +22,7 @@ func TimeDuration(i interface{}) time.Duration {
return time.Duration(Int64(i))
}
// 将变量i转换为time.Time类型
// 将变量i转换为time.Time类型, 自动识别i为时间戳或者标准化的时间字符串。
func GTime(i interface{}, format...string) *gtime.Time {
s := String(i)
if len(s) == 0 {

View File

@ -5,19 +5,7 @@ import (
"github.com/gogf/gf/g/util/gconv"
)
type User struct {
Id int
}
type RPCResponse struct {
ID interface{} `json:"id,omitempty"`
JsonRPC string `json:"jsonrpc"`
Error *User `json:"error,omitempty"`
Result interface{} `json:"result,omitempty"`
}
func main() {
var rpc RPCResponse
fmt.Println(rpc.Error)
fmt.Println(gconv.Map(rpc))
t := gconv.GTime("2010-10-10 00:00:01")
fmt.Println(t.String())
}