gconv改进

This commit is contained in:
john
2018-09-28 13:33:41 +08:00
parent a68ee95575
commit d7d3e6a50d
5 changed files with 200 additions and 103 deletions

View File

@ -33,6 +33,8 @@ func Convert(i interface{}, t string, params...interface{}) interface{} {
case "bool": return Bool(i)
case "string": return String(i)
case "[]byte": return Bytes(i)
case "[]int": return Ints(i)
case "[]string": return Strings(i)
case "time.Time":
if len(params) > 0 {
return Time(i, String(params[0]))

157
g/util/gconv/gconv_slice.go Normal file
View File

@ -0,0 +1,157 @@
// Copyright 2017 gf Author(https://gitee.com/johng/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://gitee.com/johng/gf.
package gconv
import "fmt"
// 任意类型转换为[]int类型
func Ints(i interface{}) []int {
if i == nil {
return nil
}
if r, ok := i.([]int); ok {
return r
} else {
array := make([]int, 0)
switch i.(type) {
case []string:
for _, v := range i.([]string) {
array = append(array, Int(v))
}
case []int8:
for _, v := range i.([]int8) {
array = append(array, Int(v))
}
case []int16:
for _, v := range i.([]int16) {
array = append(array, Int(v))
}
case []int32:
for _, v := range i.([]int32) {
array = append(array, Int(v))
}
case []int64:
for _, v := range i.([]int64) {
array = append(array, Int(v))
}
case []uint:
for _, v := range i.([]uint) {
array = append(array, Int(v))
}
case []uint8:
for _, v := range i.([]uint8) {
array = append(array, Int(v))
}
case []uint16:
for _, v := range i.([]uint16) {
array = append(array, Int(v))
}
case []uint32:
for _, v := range i.([]uint32) {
array = append(array, Int(v))
}
case []uint64:
for _, v := range i.([]uint64) {
array = append(array, Int(v))
}
case []bool:
for _, v := range i.([]bool) {
array = append(array, Int(v))
}
case []float32:
for _, v := range i.([]float32) {
array = append(array, Int(v))
}
case []float64:
for _, v := range i.([]float64) {
array = append(array, Int(v))
}
case []interface{}:
for _, v := range i.([]interface{}) {
array = append(array, Int(v))
}
}
if len(array) > 0 {
return array
}
}
return []int{Int(i)}
}
// 任意类型转换为[]string类型
func Strings(i interface{}) []string {
if i == nil {
return nil
}
if r, ok := i.([]string); ok {
return r
} else {
array := make([]string, 0)
switch i.(type) {
case []int:
for _, v := range i.([]int) {
array = append(array, String(v))
}
case []int8:
for _, v := range i.([]int8) {
array = append(array, String(v))
}
case []int16:
for _, v := range i.([]int16) {
array = append(array, String(v))
}
case []int32:
for _, v := range i.([]int32) {
array = append(array, String(v))
}
case []int64:
for _, v := range i.([]int64) {
array = append(array, String(v))
}
case []uint:
for _, v := range i.([]uint) {
array = append(array, String(v))
}
case []uint8:
for _, v := range i.([]uint8) {
array = append(array, String(v))
}
case []uint16:
for _, v := range i.([]uint16) {
array = append(array, String(v))
}
case []uint32:
for _, v := range i.([]uint32) {
array = append(array, String(v))
}
case []uint64:
for _, v := range i.([]uint64) {
array = append(array, String(v))
}
case []bool:
for _, v := range i.([]bool) {
array = append(array, String(v))
}
case []float32:
for _, v := range i.([]float32) {
array = append(array, String(v))
}
case []float64:
for _, v := range i.([]float64) {
array = append(array, String(v))
}
case []interface{}:
for _, v := range i.([]interface{}) {
array = append(array, String(v))
}
}
if len(array) > 0 {
return array
}
}
return []string{fmt.Sprintf("%v", i)}
}

View File

@ -1,83 +0,0 @@
// Copyright 2017 gf Author(https://gitee.com/johng/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://gitee.com/johng/gf.
package gconv
import "fmt"
// 任意类型转换为[]string类型
func Strings(i interface{}) []string {
if i == nil {
return nil
}
if r, ok := i.([]string); ok {
return r
} else {
array := make([]string, 0)
switch i.(type) {
case []int:
for _, v := range i.([]int) {
array = append(array, String(v))
}
case []int8:
for _, v := range i.([]int8) {
array = append(array, String(v))
}
case []int16:
for _, v := range i.([]int16) {
array = append(array, String(v))
}
case []int32:
for _, v := range i.([]int32) {
array = append(array, String(v))
}
case []int64:
for _, v := range i.([]int64) {
array = append(array, String(v))
}
case []uint:
for _, v := range i.([]uint) {
array = append(array, String(v))
}
case []uint8:
for _, v := range i.([]uint8) {
array = append(array, String(v))
}
case []uint16:
for _, v := range i.([]uint16) {
array = append(array, String(v))
}
case []uint32:
for _, v := range i.([]uint32) {
array = append(array, String(v))
}
case []uint64:
for _, v := range i.([]uint64) {
array = append(array, String(v))
}
case []bool:
for _, v := range i.([]bool) {
array = append(array, String(v))
}
case []float32:
for _, v := range i.([]float32) {
array = append(array, String(v))
}
case []float64:
for _, v := range i.([]float64) {
array = append(array, String(v))
}
case []interface{}:
for _, v := range i.([]interface{}) {
array = append(array, String(v))
}
}
if len(array) > 0 {
return array
}
}
return []string{fmt.Sprintf("%v", i)}
}

View File

@ -11,6 +11,8 @@ import (
"reflect"
"github.com/fatih/structs"
"strings"
"errors"
"fmt"
)
// 将params键值对参数映射到对应的struct对象属性上第三个参数mapping为非必需表示自定义名称与属性名称的映射关系。
@ -40,7 +42,9 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
elem := reflect.ValueOf(objPointer).Elem()
// 如果给定的参数不是map类型那么直接将参数值映射到第一个属性上
if !isParamMap {
bindVarToStructByIndex(elem, 0, params)
if err := bindVarToStructByIndex(elem, 0, params); err != nil {
return err
}
return nil
}
// 标签映射关系map如果有的话
@ -60,7 +64,9 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
for mappingk, mappingv := range attrMapping[0] {
if v, ok := paramsMap[mappingk]; ok {
dmap[mappingv] = true
bindVarToStruct(elem, mappingv, v)
if err := bindVarToStruct(elem, mappingv, v); err != nil {
return err
}
}
}
}
@ -71,7 +77,9 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
}
if v, ok := paramsMap[tagk]; ok {
dmap[tagv] = true
bindVarToStruct(elem, tagv, v)
if err := bindVarToStruct(elem, tagv, v); err != nil {
return err
}
}
}
// 最后按照默认规则进行匹配
@ -82,39 +90,43 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
}
// 后续tag逻辑中会处理的key(重复的键名)这里便不处理
if _, ok := tagmap[mapk]; !ok {
bindVarToStruct(elem, name, mapv)
if err := bindVarToStruct(elem, name, mapv); err != nil {
return err
}
}
}
return nil
}
// 将参数值绑定到对象指定名称的属性上
func bindVarToStruct(elem reflect.Value, name string, value interface{}) {
func bindVarToStruct(elem reflect.Value, name string, value interface{}) error {
structFieldValue := elem.FieldByName(name)
// 键名与对象属性匹配检测
if !structFieldValue.IsValid() {
return
return errors.New(fmt.Sprintf(`invalid struct attribute of name "%s"`, name))
}
// CanSet的属性必须为公开属性(首字母大写)
if !structFieldValue.CanSet() {
return
return errors.New(fmt.Sprintf(`struct attribute of name "%s" cannot be set`, name))
}
// 必须将value转换为struct属性的数据类型这里必须用到gconv包
structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String())))
return nil
}
// 将参数值绑定到对象指定索引位置的属性上
func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) {
func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) error {
structFieldValue := elem.FieldByIndex([]int{index})
// 键名与对象属性匹配检测
if !structFieldValue.IsValid() {
return
return errors.New(fmt.Sprintf("invalid struct attribute at index %d", index))
}
// CanSet的属性必须为公开属性(首字母大写)
if !structFieldValue.CanSet() {
return
return errors.New(fmt.Sprintf("struct attribute cannot be set at index %d", index))
}
// 必须将value转换为struct属性的数据类型这里必须用到gconv包
structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String())))
return nil
}

View File

@ -1,19 +1,28 @@
package main
import (
"gitee.com/johng/gf/g/os/glog"
"time"
"gitee.com/johng/gf/g"
"encoding/json"
"fmt"
)
func main() {
g.Config().AddPath("eeee")
g.Config().AddPath(".")
glog.SetPath(g.Config().GetString("logPath"))
glog.SetPath("/tmp/test-logs")
for {
glog.Println("1")
time.Sleep(time.Second)
type B struct {
Name string
}
type A struct {
Name string
Child B
}
a := A {
Name : "A",
Child : B {
Name : "B",
},
}
b, _ := json.Marshal(a)
a2 := new(A)
json.Unmarshal(b, a2)
fmt.Println(*a2)
}