gconv包增加按照类型名称字符串进行类型转换,gutil增加MapToStruct方法,gjson/gparser改进ToStruct方法实现,gdb.Map类型增加ToStruct方法

This commit is contained in:
John
2018-04-29 21:33:47 +08:00
parent eca987c362
commit ed9bd57d7c
9 changed files with 139 additions and 53 deletions

View File

@ -13,6 +13,7 @@ import (
"database/sql"
"gitee.com/johng/gf/g/util/gconv"
"gitee.com/johng/gf/g/util/grand"
"gitee.com/johng/gf/g/util/gutil"
_ "github.com/lib/pq"
_ "github.com/go-sql-driver/mysql"
)
@ -201,10 +202,15 @@ func newDb (masterNode *ConfigNode, slaveNode *ConfigNode) (*Db, error) {
}, nil
}
// 将Map变量映射到指定的struct对象中注意参数应当是一个对象的指针
func (m Map) ToStruct(obj interface{}) error {
return gutil.MapToStruct(m, obj)
}
// 将结果列表按照指定的字段值做map[string]Map
func (list List) ToStringMap(key string) map[string]Map {
func (l List) ToStringMap(key string) map[string]Map {
m := make(map[string]Map)
for _, item := range list {
for _, item := range l {
if v, ok := item[key]; ok {
m[gconv.String(v)] = item
}
@ -213,9 +219,9 @@ func (list List) ToStringMap(key string) map[string]Map {
}
// 将结果列表按照指定的字段值做map[int]Map
func (list List) ToIntMap(key string) map[int]Map {
func (l List) ToIntMap(key string) map[int]Map {
m := make(map[int]Map)
for _, item := range list {
for _, item := range l {
if v, ok := item[key]; ok {
m[gconv.Int(v)] = item
}
@ -224,9 +230,9 @@ func (list List) ToIntMap(key string) map[int]Map {
}
// 将结果列表按照指定的字段值做map[uint]Map
func (list List) ToUintMap(key string) map[uint]Map {
func (l List) ToUintMap(key string) map[uint]Map {
m := make(map[uint]Map)
for _, item := range list {
for _, item := range l {
if v, ok := item[key]; ok {
m[gconv.Uint(v)] = item
}

View File

@ -16,6 +16,7 @@ import (
"encoding/json"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/util/gconv"
"gitee.com/johng/gf/g/util/gutil"
"gitee.com/johng/gf/g/encoding/gxml"
"gitee.com/johng/gf/g/encoding/gyaml"
"gitee.com/johng/gf/g/encoding/gtoml"
@ -240,7 +241,7 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
value = j.convertValue(value)
// 初始化判断
if *j.p == nil {
if isNumeric(array[0]) {
if gutil.IsNumeric(array[0]) {
*j.p = make([]interface{}, 0)
} else {
*j.p = make(map[string]interface{})
@ -267,7 +268,7 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
goto done
}
// 创建新节点
if isNumeric(array[i + 1]) {
if gutil.IsNumeric(array[i + 1]) {
// 创建array节点
n, _ := strconv.Atoi(array[i + 1])
var v interface{} = make([]interface{}, n + 1)
@ -287,7 +288,7 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
case []interface{}:
// 键名与当前指针类型不符合,需要执行**覆盖操作**
if !isNumeric(array[i]) {
if !gutil.IsNumeric(array[i]) {
if i == length - 1 {
*pointer = map[string]interface{}{ array[i] : value }
} else {
@ -319,7 +320,7 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
j.setPointerWithValue(pointer, array[i], value)
}
} else {
if isNumeric(array[i + 1]) {
if gutil.IsNumeric(array[i + 1]) {
n, _ := strconv.Atoi(array[i + 1])
if len((*pointer).([]interface{})) > valn {
(*pointer).([]interface{})[valn] = make([]interface{}, n + 1)
@ -346,7 +347,7 @@ func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
if removed && value == nil {
goto done
}
if isNumeric(array[i]) {
if gutil.IsNumeric(array[i]) {
n, _ := strconv.Atoi(array[i])
s := make([]interface{}, n + 1)
if i == length - 1 {
@ -518,7 +519,7 @@ func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interfac
return &v
}
case []interface{}:
if isNumeric(key) {
if gutil.IsNumeric(key) {
n, err := strconv.Atoi(key)
if err == nil && len((*pointer).([]interface{})) > n {
return &(*pointer).([]interface{})[n]
@ -584,12 +585,9 @@ func (j *Json) ToToml() ([]byte, error) {
return gtoml.Encode(*(j.p))
}
// 判断所给字符串是否为数字
func isNumeric(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] < byte('0') || s[i] > byte('9') {
return false
}
}
return true
// 转换为指定的struct对象
func (j *Json) ToStruct(o interface{}) error {
j.mu.RLock()
defer j.mu.RUnlock()
return gutil.MapToStruct(j.ToMap(), o)
}

View File

@ -9,7 +9,6 @@ package gparser
import (
"gitee.com/johng/gf/g/encoding/gjson"
"encoding/json"
)
type Parser struct {
@ -151,12 +150,8 @@ func (p *Parser) ToToml() ([]byte, error) {
}
// 将变量解析为对应的struct对象注意传递的参数为struct对象指针
func (p *Parser) ToStruct(v interface{}) error {
if c, e := p.ToJson(); e == nil {
return json.Unmarshal(c, v)
} else {
return e
}
func (p *Parser) ToStruct(o interface{}) error {
return p.json.ToStruct(o)
}
func VarToXml(value interface{}, rootTag...string) ([]byte, error) {

View File

@ -14,6 +14,29 @@ import (
"gitee.com/johng/gf/g/encoding/gbinary"
)
// 将变量i转换为字符串指定的类型t
func Convert(i interface{}, t string) interface{} {
switch t {
case "int": return Int(i)
case "int8": return Int8(i)
case "int16": return Int16(i)
case "int32": return Int32(i)
case "int64": return Int64(i)
case "uint": return Uint(i)
case "uint8": return Uint8(i)
case "uint16": return Uint16(i)
case "uint32": return Uint32(i)
case "uint64": return Uint64(i)
case "float32": return Float32(i)
case "float64": return Float64(i)
case "bool": return Bool(i)
case "string": return String(i)
case "[]byte": return Bytes(i)
default:
return i
}
}
func Bytes(i interface{}) []byte {
if i == nil {
return nil
@ -233,3 +256,4 @@ func Float64 (i interface{}) float64 {
return v
}

View File

@ -7,6 +7,33 @@
// 其他工具包
package gutil
import (
"reflect"
"gitee.com/johng/gf/g/util/gconv"
)
// 字符串首字母转换为大写
func UcFirst(s string) string {
if len(s) == 0 {
return s
}
if IsLetterLower(s[0]) {
return string(s[0] - 32) + s[1 :]
}
return s
}
// 字符串首字母转换为小写
func LcFirst(s string) string {
if len(s) == 0 {
return s
}
if IsLetterUpper(s[0]) {
return string(s[0] + 32) + s[1 :]
}
return s
}
// 便利数组查找字符串索引位置,如果不存在则返回-1使用完整遍历查找
func StringSearch (a []string, s string) int {
for i, v := range a {
@ -47,3 +74,30 @@ func IsNumeric(s string) bool {
}
return true
}
// 将map键值对映射到对应的struct对象属性上需要注意
// 1、第二个参数为struct对象指针
// 2、struct对象的公开属性才能被映射赋值
// 3、map中的键名可以为小写映射转换时会自动将键名首字母转为大写做匹配映射如果无法匹配则忽略
func MapToStruct(m map[string]interface{}, o interface{}) error {
for k, v := range m {
_MapToStructSetField(o, k, v)
}
return nil
}
func _MapToStructSetField(obj interface{}, name string, value interface{}) {
structValue := reflect.ValueOf(obj).Elem()
structFieldValue := structValue.FieldByName(UcFirst(name))
// 键名与对象属性匹配检测
if !structFieldValue.IsValid() {
//return fmt.Errorf("No such field: %s in obj", name)
return
}
// CanSet的属性必须为公开属性(首字母大写)
if !structFieldValue.CanSet() {
//return fmt.Errorf("Cannot set %s field value", name)
return
}
// 必须将value转换为struct属性的数据类型这里必须用到gconv包
structFieldValue.Set(reflect.ValueOf(gconv.Convert(value, structFieldValue.Type().String())))
}

View File

@ -445,29 +445,39 @@ func keepPing() {
}
}
// 数据库单例测试在mysql中使用 show full processlist 查看链接信息
func instance() {
fmt.Println("instance:")
db1, _ := gdb.New()
db2, _ := gdb.New()
db3, _ := gdb.New()
for {
fmt.Println("ping...")
db1.PingMaster()
db1.PingSlave()
db2.PingMaster()
db2.PingSlave()
db3.PingMaster()
db3.PingSlave()
time.Sleep(1*time.Second)
// like语句查询
func likeQuery() {
fmt.Println("likeQuery:")
if r, err := db.Table("user").Where("name like ?", "%john%").Select(); err == nil {
fmt.Println(r)
} else {
fmt.Println(err)
}
}
// mapToStruct
func mapToStruct() {
type User struct {
Uid int
Name string
}
fmt.Println("mapToStruct:")
if r, err := db.Table("user").Where("uid=?", 1).One(); err == nil {
u := User{}
if err := r.ToStruct(&u); err == nil {
fmt.Println(r)
fmt.Println(u)
} else {
fmt.Println(err)
}
} else {
fmt.Println(err)
}
}
func main() {
r, e := db.Table("user").Where("name like ?", "%john%").Select()
fmt.Println(e)
fmt.Println(r)
mapToStruct()
//create()
//create()
//insert()

View File

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

View File

@ -13,7 +13,7 @@ type gtInterface interface {
type st struct {
age int
name string
Name string
}
type mySt struct {
@ -53,7 +53,7 @@ func main() {
//// 我们需要调用的是实体结构体指针的方法注意v2与v2的区别以及方法定义的区别
//v2.MethodByName("Echo2").Call([]reflect.Value{p})
//v.MethodByName()
fmt.Println(v.Type())
fmt.Println(v.FieldByName("name"))

View File

@ -2,11 +2,10 @@ package main
import (
"fmt"
"math/rand"
"gitee.com/johng/gf/g/util/gutil"
)
func main() {
for i := 0; i < 100; i++ {
fmt.Println(rand.Intn(200))
}
fmt.Println(gutil.LcFirst("ABC"))
fmt.Println(gutil.UcFirst("abc"))
}