1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
| func checkSkipNames(a string, b []string) bool { for _, item := range b { if item == a { return true } } return false }
// 结构体的字段名称 func GetStructName(myref reflect.Value, names []string) (buffer string) { // 注:有可能传递string数组,此时没有“标题”一说,返回 if myref.Type().Name() == "string" { return } for i := 0; i < myref.NumField(); i++ { if ok := checkSkipNames(myref.Type().Field(i).Name, names); ok { continue } buffer += fmt.Sprintf("| %v ", myref.Type().Field(i).Name) } buffer += fmt.Sprintf("|\n") for i := 0; i < myref.NumField(); i++ { if ok := checkSkipNames(myref.Type().Field(i).Name, names); ok { continue } buffer += fmt.Sprintf("| --- ") } buffer += fmt.Sprintf("|\n") return }
// 将 | 替换为 <br> func replaceI(text string) (ret string) { // 下面2种方法都可以 // reg := regexp.MustCompile(`\|`) // ret = reg.ReplaceAllString(text, `${1}<br/>`) ret = strings.Replace(text, "|", "<br>", -1) // fmt.Printf("!!! %q\n", ret) return ret }
// 结构体的值 func GetStructValue(myref reflect.Value, names []string) (buffer string) { // 注:有可能传递string数组,此时没有“字段”一说,返回原本的内容 if myref.Type().Name() == "string" { return myref.Interface().(string) }
for i := 0; i < myref.NumField(); i++ { if ok := checkSkipNames(myref.Type().Field(i).Name, names); ok { continue } // 判断是否包含|,有则替换,其必须是string类型,其它保持原有的 t := myref.Field(i).Type().Name() if t == "string" { var str string = myref.Field(i).Interface().(string) str = replaceI(str) buffer += fmt.Sprintf("| %v ", str) } else { buffer += fmt.Sprintf("| %v ", myref.Field(i).Interface()) } } buffer += fmt.Sprintf("|\n")
return }
func PrintStructTable(data interface{}, title string, skipNames ...string) { var w io.Writer w = os.Stdout // set to stdout buffer, num := PrintStructTable2Buffer(data, title, skipNames...) fmt.Fprintf(w, "total: %v\n", num) fmt.Fprintf(w, "%v\n", buffer) }
/* 功能:指定结构体data,其可为slice map 单独结构体 指定自定义标题,为空则使用结构体字段 指定忽略的字段名称(即结构体字段的变量) 按结构体定义的顺序列出,如自定义标题,则必须保证一致。 */ func PrintStructTable2Buffer(data interface{}, title string, skipNames ...string) (buffer string, num int) { buffer = ""
t := reflect.TypeOf(data) v := reflect.ValueOf(data)
var skipNamess []string for _, item := range skipNames { skipNamess = append(skipNamess, item) }
// 打印结构体字段标志 innertitle := false printHead := false if len(title) == 0 { innertitle = true }
// 不同类型的,其索引方式不同,故一一判断使用 switch t.Kind() { case reflect.Slice, reflect.Array: num = v.Len() if innertitle { buffer += GetStructName(v.Index(0), skipNamess) } else { buffer += fmt.Sprintln(title) } for i := 0; i < v.Len(); i++ { buffer += GetStructValue(v.Index(i), skipNamess) } case reflect.Map: num = v.Len() iter := v.MapRange() for iter.Next() { if !printHead { if innertitle { buffer += GetStructName(iter.Value(), skipNamess) } else { buffer += fmt.Sprintln(title) } printHead = true } buffer += GetStructValue(iter.Value(), skipNamess) } default: num = 1 // 单独结构体不能用Len,单独赋值 if !printHead { if innertitle { buffer += GetStructName(v, skipNamess) } else { buffer += fmt.Sprintln(title) } printHead = true } buffer += GetStructValue(v, skipNamess) }
return }
|