123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- package typekit
- import (
- "fmt"
- "reflect"
- "sort"
- "strings"
- )
- const (
- colorReset = "\033[0m"
- colorStruct = "\033[34m"
- colorField = "\033[32m"
- colorMap = "\033[33m"
- colorSlice = "\033[35m"
- colorValue = "\033[31m"
- colorKey = "\033[36m"
- )
- func PrettyPrint(v interface{}) string {
- return prettyPrint(reflect.ValueOf(v), 0, make(map[uintptr]bool)).String()
- }
- type lines []string
- func (l lines) String() string {
- return strings.Join(l, "\n")
- }
- func prettyPrint(v reflect.Value, indentLevel int, visited map[uintptr]bool) lines {
- original := v
- // 改进的指针/接口处理逻辑
- for {
- switch v.Kind() {
- case reflect.Ptr:
- if v.IsNil() {
- return lines{colorValue + "nil" + colorReset}
- }
- ptr := v.Pointer() // 使用正确获取指针值的方法
- if visited[ptr] {
- // 正确格式化指针地址
- return lines{fmt.Sprintf("%s&%p%s", colorValue, v.Interface(), colorReset)}
- }
- visited[ptr] = true
- original = v
- v = v.Elem()
- case reflect.Interface:
- if v.IsNil() {
- return lines{colorValue + "nil" + colorReset}
- }
- v = v.Elem()
- default:
- goto END_DEREF
- }
- }
- END_DEREF:
- switch v.Kind() {
- case reflect.Struct:
- return printStruct(v, indentLevel, visited)
- case reflect.Map:
- return printMap(v, indentLevel, visited)
- case reflect.Slice, reflect.Array:
- return printSlice(v, indentLevel, visited)
- case reflect.String:
- return lines{fmt.Sprintf("%s%q%s", colorValue, v.String(), colorReset)}
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return lines{fmt.Sprintf("%s%d%s", colorValue, v.Int(), colorReset)}
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return lines{fmt.Sprintf("%s%d%s", colorValue, v.Uint(), colorReset)}
- case reflect.Float32, reflect.Float64:
- return lines{fmt.Sprintf("%s%.2f%s", colorValue, v.Float(), colorReset)}
- case reflect.Bool:
- return lines{fmt.Sprintf("%s%t%s", colorValue, v.Bool(), colorReset)}
- default:
- if original.Kind() == reflect.Ptr {
- return lines{fmt.Sprintf("%s%v%s", colorValue, original.Interface(), colorReset)}
- }
- return lines{fmt.Sprintf("%s%v%s", colorValue, v.Interface(), colorReset)}
- }
- }
- // 完整实现结构体打印
- func printStruct(v reflect.Value, indentLevel int, visited map[uintptr]bool) lines {
- header := fmt.Sprintf("%s%s%s%s:",
- strings.Repeat(" ", indentLevel),
- colorStruct,
- v.Type().String(),
- colorReset,
- )
- result := lines{header}
- for i := 0; i < v.NumField(); i++ {
- field := v.Type().Field(i)
- fieldValue := v.Field(i)
- fieldLines := prettyPrint(fieldValue, indentLevel+1, visited)
- fieldHeader := fmt.Sprintf("%s%s%s: ",
- strings.Repeat(" ", indentLevel+1),
- colorField,
- field.Name,
- )
- if len(fieldLines) == 0 {
- result = append(result, fieldHeader+colorValue+"<invalid>"+colorReset)
- continue
- }
- result = append(result, fieldHeader+fieldLines[0])
- for _, line := range fieldLines[1:] {
- result = append(result,
- strings.Repeat(" ", indentLevel+1)+" "+line)
- }
- }
- return result
- }
- // 完整实现map打印
- func printMap(v reflect.Value, indentLevel int, visited map[uintptr]bool) lines {
- header := fmt.Sprintf("%s%s%s%s:",
- strings.Repeat(" ", indentLevel),
- colorMap,
- v.Type().String(),
- colorReset,
- )
- result := lines{header}
- keys := v.MapKeys()
- sort.Slice(keys, func(i, j int) bool {
- return fmt.Sprintf("%v", keys[i]) < fmt.Sprintf("%v", keys[j])
- })
- for _, key := range keys {
- keyLines := prettyPrint(key, 0, visited)
- valueLines := prettyPrint(v.MapIndex(key), indentLevel+1, visited)
- keyHeader := fmt.Sprintf("%s%s%s: ",
- strings.Repeat(" ", indentLevel+1),
- colorKey,
- strings.Join(keyLines, ""),
- )
- if len(valueLines) == 0 {
- result = append(result, keyHeader+colorValue+"<invalid>"+colorReset)
- continue
- }
- result = append(result, keyHeader+valueLines[0])
- for _, line := range valueLines[1:] {
- result = append(result,
- strings.Repeat(" ", indentLevel+1)+" "+line)
- }
- }
- return result
- }
- // 完整实现slice/array打印
- func printSlice(v reflect.Value, indentLevel int, visited map[uintptr]bool) lines {
- header := fmt.Sprintf("%s%s%s%s:",
- strings.Repeat(" ", indentLevel),
- colorSlice,
- v.Type().String(),
- colorReset,
- )
- result := lines{header}
- for i := 0; i < v.Len(); i++ {
- elemLines := prettyPrint(v.Index(i), indentLevel+1, visited)
- bullet := fmt.Sprintf("%s- ",
- strings.Repeat(" ", indentLevel+1),
- )
- if len(elemLines) == 0 {
- result = append(result, bullet+colorValue+"<invalid>"+colorReset)
- continue
- }
- result = append(result, bullet+elemLines[0])
- for _, line := range elemLines[1:] {
- result = append(result,
- strings.Repeat(" ", indentLevel+1)+" "+line)
- }
- }
- return result
- }
- /*
- // 修正后的测试用例
- type Person struct {
- Name string
- Age int
- Hobbies []string
- Address struct {
- City string
- State string
- }
- Metadata map[string]interface{}
- }
- func main() {
- p := Person{
- Name: "Alice",
- Age: 30,
- Hobbies: []string{"Reading", "Hiking"},
- Metadata: map[string]interface{}{
- "id": 123,
- "scores": []float64{98.5, 87.2},
- "nested": map[string]interface{}{"a": 1, "b": 2},
- },
- }
- p.Address.City = "New York"
- p.Address.State = "NY"
- p.Metadata["self_ref"] = &p // 正确设置循环引用
- fmt.Println(PrettyPrint(p))
- }
- */
|