diff --git a/g/util/gconv/gconv.go b/g/util/gconv/gconv.go index d061b3e59..8fcb043b7 100644 --- a/g/util/gconv/gconv.go +++ b/g/util/gconv/gconv.go @@ -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])) diff --git a/g/util/gconv/gconv_slice.go b/g/util/gconv/gconv_slice.go new file mode 100644 index 000000000..ade37678b --- /dev/null +++ b/g/util/gconv/gconv_slice.go @@ -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)} +} \ No newline at end of file diff --git a/g/util/gconv/gconv_strings.go b/g/util/gconv/gconv_strings.go deleted file mode 100644 index 9df780935..000000000 --- a/g/util/gconv/gconv_strings.go +++ /dev/null @@ -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)} -} \ No newline at end of file diff --git a/g/util/gconv/gconv_struct.go b/g/util/gconv/gconv_struct.go index f587dd3e9..858d752cd 100644 --- a/g/util/gconv/gconv_struct.go +++ b/g/util/gconv/gconv_struct.go @@ -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 } diff --git a/geg/other/test.go b/geg/other/test.go index 309f5e602..588aca492 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -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) }