1
0
mirror of https://github.com/gogf/gf.git synced 2025-04-05 03:05:05 +08:00
This commit is contained in:
John Guo 2022-03-10 21:12:24 +08:00
parent 87b1433473
commit afa1f78a02
4 changed files with 164 additions and 15 deletions

View File

@ -62,3 +62,28 @@ func OriginTypeAndKind(value interface{}) (out OriginTypeAndKindOutput) {
}
return
}
// ReflectValueToInterface converts reflect value to its interface type.
func ReflectValueToInterface(v reflect.Value) (value interface{}, ok bool) {
if v.IsValid() && v.CanInterface() {
return v.Interface(), true
}
switch v.Kind() {
case reflect.Bool:
return v.Bool(), true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int(), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint(), true
case reflect.Float32, reflect.Float64:
return v.Float(), true
case reflect.Complex64, reflect.Complex128:
return v.Complex(), true
case reflect.String:
return v.String(), true
case reflect.Ptr:
return ReflectValueToInterface(v.Elem())
default:
return nil, false
}
}

View File

@ -122,9 +122,6 @@ func Fields(in FieldsInput) ([]Field, error) {
for index := 0; index < len(rangeFields); index++ {
field := rangeFields[index]
if !field.IsExported() {
continue
}
currentLevelFieldMap[field.Name()] = field
}
@ -133,10 +130,6 @@ func Fields(in FieldsInput) ([]Field, error) {
if _, ok = fieldFilterMap[field.Name()]; ok {
continue
}
// It only retrieves exported attributes.
if !field.IsExported() {
continue
}
if field.IsEmbedded() {
if in.RecursiveOption != RecursiveOptionNone {
switch in.RecursiveOption {

View File

@ -13,6 +13,7 @@ import (
"reflect"
"strings"
"github.com/gogf/gf/v2/internal/utils"
"github.com/gogf/gf/v2/os/gstructs"
"github.com/gogf/gf/v2/text/gstr"
)
@ -79,14 +80,31 @@ type doDumpOption struct {
}
func doDump(value interface{}, indent string, buffer *bytes.Buffer, option doDumpOption) {
if value == nil {
buffer.WriteString(`<nil>`)
return
}
var reflectValue reflect.Value
if v, ok := value.(reflect.Value); ok {
reflectValue = v
if v.CanInterface() {
value = v.Interface()
} else {
if convertedValue, ok := utils.ReflectValueToInterface(v); ok {
value = convertedValue
}
}
} else {
reflectValue = reflect.ValueOf(value)
}
// Double check nil value.
if value == nil {
buffer.WriteString(`<nil>`)
return
}
var (
reflectValue = reflect.ValueOf(value)
reflectKind = reflectValue.Kind()
reflectTypeName = reflect.TypeOf(value).String()
reflectTypeName = reflectValue.Type().String()
newIndent = indent + dumpIndent
)
reflectTypeName = strings.ReplaceAll(reflectTypeName, `[]uint8`, `[]byte`)
@ -142,13 +160,13 @@ func doDump(value interface{}, indent string, buffer *bytes.Buffer, option doDum
doDumpNumber(exportInternalInput)
case reflect.Chan:
buffer.WriteString(fmt.Sprintf(`<%s>`, reflect.TypeOf(value).String()))
buffer.WriteString(fmt.Sprintf(`<%s>`, reflectTypeName))
case reflect.Func:
if reflectValue.IsNil() || !reflectValue.IsValid() {
buffer.WriteString(`<nil>`)
} else {
buffer.WriteString(fmt.Sprintf(`<%s>`, reflect.TypeOf(value).String()))
buffer.WriteString(fmt.Sprintf(`<%s>`, reflectTypeName))
}
default:
@ -195,7 +213,7 @@ func doDumpSlice(in doDumpInternalInput) {
}
for i := 0; i < in.ReflectValue.Len(); i++ {
in.Buffer.WriteString(in.NewIndent)
doDump(in.ReflectValue.Index(i).Interface(), in.NewIndent, in.Buffer, in.Option)
doDump(in.ReflectValue.Index(i), in.NewIndent, in.Buffer, in.Option)
in.Buffer.WriteString(",\n")
}
in.Buffer.WriteString(fmt.Sprintf("%s]", in.Indent))
@ -254,7 +272,7 @@ func doDumpMap(in doDumpInternalInput) {
))
}
// Map value dump.
doDump(in.ReflectValue.MapIndex(mapKey).Interface(), in.NewIndent, in.Buffer, in.Option)
doDump(in.ReflectValue.MapIndex(mapKey), in.NewIndent, in.Buffer, in.Option)
in.Buffer.WriteString(",\n")
}
in.Buffer.WriteString(fmt.Sprintf("%s}", in.Indent))
@ -319,7 +337,7 @@ func doDumpStruct(in doDumpInternalInput) {
field.Name(),
strings.Repeat(" ", maxSpaceNum-tmpSpaceNum+1),
))
doDump(field.Value.Interface(), in.NewIndent, in.Buffer, in.Option)
doDump(field.Value, in.NewIndent, in.Buffer, in.Option)
in.Buffer.WriteString(",\n")
}
in.Buffer.WriteString(fmt.Sprintf("%s}", in.Indent))
@ -371,7 +389,13 @@ func doDumpBool(in doDumpInternalInput) {
}
func doDumpDefault(in doDumpInternalInput) {
s := fmt.Sprintf("%v", in.Value)
var s string
if in.ReflectValue.CanInterface() {
s = fmt.Sprintf("%v", in.ReflectValue.Interface())
}
if s == "" {
s = fmt.Sprintf("%v", in.Value)
}
s = gstr.Trim(s, `<>`)
if !in.Option.WithType {
in.Buffer.WriteString(s)

View File

@ -7,6 +7,7 @@
package gutil_test
import (
"bytes"
"testing"
"github.com/gogf/gf/v2/net/ghttp"
@ -142,3 +143,109 @@ func Test_Dump_Slashes(t *testing.T) {
gutil.DumpWithType(req.Content)
})
}
// https://github.com/gogf/gf/issues/1661
func Test_Dump_Issue1661(t *testing.T) {
type B struct {
ba int
bb string
}
type A struct {
aa int
ab string
cc []B
}
gtest.C(t, func(t *gtest.T) {
var q1 []A
var q2 []A
q2 = make([]A, 0)
q1 = []A{{aa: 1, ab: "1", cc: []B{{ba: 1}, {ba: 2}, {ba: 3}}}, {aa: 2, ab: "2", cc: []B{{ba: 1}, {ba: 2}, {ba: 3}}}}
for _, q1v := range q1 {
x := []string{"11", "22"}
for _, iv2 := range x {
ls := q1v
for i, _ := range ls.cc {
sj := iv2
ls.cc[i].bb = sj
}
q2 = append(q2, ls)
}
}
buffer := bytes.NewBuffer(nil)
gutil.DumpTo(buffer, q2, gutil.DumpOption{})
t.Assert(buffer.String(), `[
{
aa: 1,
ab: "1",
cc: [
{
ba: 1,
bb: "22",
},
{
ba: 2,
bb: "22",
},
{
ba: 3,
bb: "22",
},
],
},
{
aa: 1,
ab: "1",
cc: [
{
ba: 1,
bb: "22",
},
{
ba: 2,
bb: "22",
},
{
ba: 3,
bb: "22",
},
],
},
{
aa: 2,
ab: "2",
cc: [
{
ba: 1,
bb: "22",
},
{
ba: 2,
bb: "22",
},
{
ba: 3,
bb: "22",
},
],
},
{
aa: 2,
ab: "2",
cc: [
{
ba: 1,
bb: "22",
},
{
ba: 2,
bb: "22",
},
{
ba: 3,
bb: "22",
},
],
},
]`)
})
}