github.com/searKing/golang/go@v1.2.117/reflect/truncate.go (about) 1 // Copyright 2022 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package reflect 6 7 import ( 8 "bytes" 9 "fmt" 10 "reflect" 11 "strings" 12 13 bytes_ "github.com/searKing/golang/go/bytes" 14 strings_ "github.com/searKing/golang/go/strings" 15 ) 16 17 // TruncateString reset string, useful for dump into log if some field is huge 18 // v is truncated in place 19 // return interface{} same as truncated v for stream-like api 20 func TruncateString(v any, n int) any { 21 return Truncate(v, func(v any) bool { 22 _, ok := v.(string) 23 return ok 24 }, n) 25 } 26 27 // TruncateBytes reset bytes, useful for dump into log if some field is huge 28 // v is truncated in place 29 // return interface{} same as truncated v for stream-like api 30 func TruncateBytes(v any, n int) any { 31 return Truncate(v, func(v any) bool { 32 _, ok := v.([]byte) 33 return ok 34 }, n) 35 } 36 37 // Truncate reset bytes and string at each run of value c satisfying f(c), useful for dump into log if some field is huge 38 // v is truncated in place 39 // return interface{} same as truncated v for stream-like api 40 func Truncate(v any, f func(v any) bool, n int) any { 41 truncate(reflect.ValueOf(v), f, n) 42 return v 43 } 44 45 func truncate(v reflect.Value, f func(v any) bool, n int) { 46 if !v.IsValid() { 47 return 48 } 49 if IsNilType(v.Type()) { 50 return 51 } 52 53 if v.CanInterface() { 54 vv := v.Interface() 55 if f(vv) { 56 // handle v in place, stop visit sons 57 if v.CanSet() { 58 switch vv := vv.(type) { 59 case []byte: 60 if len(vv) <= n { 61 break 62 } 63 var buf bytes.Buffer 64 buf.WriteString(fmt.Sprintf("size: %d, bytes: ", len(vv))) 65 buf.Write(bytes_.Truncate(vv, n)) 66 v.SetBytes(buf.Bytes()) 67 return 68 case string: 69 if len(vv) <= n { 70 break 71 } 72 var buf strings.Builder 73 buf.WriteString(fmt.Sprintf("size: %d, string: ", len(vv))) 74 buf.WriteString(strings_.Truncate(vv, n)) 75 v.SetString(buf.String()) 76 return 77 } 78 } 79 return 80 } 81 } 82 83 // handle v's sons 84 switch v.Kind() { 85 case reflect.Slice, reflect.Array: 86 for i := 0; i < v.Len(); i++ { 87 truncate(v.Index(i), f, n) 88 } 89 case reflect.Struct: 90 // Scan typ for fields to include. 91 for i := 0; i < v.NumField(); i++ { 92 truncate(v.Field(i), f, n) 93 } 94 case reflect.Map: 95 iter := v.MapRange() 96 for iter.Next() { 97 //truncate(iter.Key(), f, n) // Key of Map is not addressable 98 truncate(iter.Value(), f, n) 99 } 100 case reflect.Ptr: 101 truncate(reflect.Indirect(v), f, n) 102 } 103 return 104 }