Codebase list golang-github-go-logr-logr / 70814c9
funcr: Add mostly-json-compatible `omitempty` Needed for upcoming changes. This does not support the "string" tag. before: ``` BenchmarkFuncrLogInfoOneArg-6 2048360 580.5 ns/op BenchmarkFuncrJSONLogInfoOneArg-6 1801868 664.4 ns/op BenchmarkFuncrLogInfoSeveralArgs-6 1000000 1146 ns/op BenchmarkFuncrJSONLogInfoSeveralArgs-6 948682 1262 ns/op BenchmarkFuncrLogV0Info-6 1000000 1152 ns/op BenchmarkFuncrJSONLogV0Info-6 956329 1251 ns/op BenchmarkFuncrLogV9Info-6 14943397 81.79 ns/op BenchmarkFuncrJSONLogV9Info-6 14859470 81.85 ns/op BenchmarkFuncrLogError-6 867200 1388 ns/op BenchmarkFuncrJSONLogError-6 803006 1491 ns/op ``` after: ``` BenchmarkFuncrLogInfoOneArg-6 2062489 581.2 ns/op BenchmarkFuncrJSONLogInfoOneArg-6 1797045 665.0 ns/op BenchmarkFuncrLogInfoSeveralArgs-6 1000000 1153 ns/op BenchmarkFuncrJSONLogInfoSeveralArgs-6 951409 1259 ns/op BenchmarkFuncrLogV0Info-6 1000000 1185 ns/op BenchmarkFuncrJSONLogV0Info-6 951258 1260 ns/op BenchmarkFuncrLogV9Info-6 15033921 80.90 ns/op BenchmarkFuncrJSONLogV9Info-6 14826121 80.06 ns/op BenchmarkFuncrLogError-6 868934 1269 ns/op BenchmarkFuncrJSONLogError-6 849028 1359 ns/op ``` Tim Hockin 2 years ago
2 changed file(s) with 254 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
356356 // reflect says this field is only defined for non-exported fields.
357357 continue
358358 }
359 if i > 0 {
360 buf.WriteByte(',')
361 }
362 buf.WriteByte('"')
363359 name := fld.Name
360 omitempty := false
364361 if tag, found := fld.Tag.Lookup("json"); found {
362 if tag == "-" {
363 continue
364 }
365365 if comma := strings.Index(tag, ","); comma != -1 {
366 name = tag[:comma]
366 if n := tag[:comma]; n != "" {
367 name = n
368 }
369 rest := tag[comma:]
370 if strings.Contains(rest, ",omitempty,") || strings.HasSuffix(rest, ",omitempty") {
371 omitempty = true
372 }
367373 } else {
368374 name = tag
369375 }
370376 }
377 if omitempty && isEmpty(v.Field(i)) {
378 continue
379 }
380 if i > 0 {
381 buf.WriteByte(',')
382 }
383 buf.WriteByte('"')
371384 buf.WriteString(name)
372385 buf.WriteByte('"')
373386 buf.WriteByte(':')
414427 return fmt.Sprintf(`"<unhandled-%s>"`, t.Kind().String())
415428 }
416429
430 func isEmpty(v reflect.Value) bool {
431 switch v.Kind() {
432 case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
433 return v.Len() == 0
434 case reflect.Bool:
435 return !v.Bool()
436 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
437 return v.Int() == 0
438 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
439 return v.Uint() == 0
440 case reflect.Float32, reflect.Float64:
441 return v.Float() == 0
442 case reflect.Complex64, reflect.Complex128:
443 return v.Complex() == 0
444 case reflect.Interface, reflect.Ptr:
445 return v.IsNil()
446 }
447 return false
448 }
449
417450 type callerID struct {
418451 File string `json:"file"`
419452 Line int `json:"line"`
6060 return "Error(): you should not see this"
6161 }
6262
63 type TjsontagsString struct {
64 String1 string `json:"string1"` // renamed
65 String2 string `json:"-"` // ignored
66 String3 string `json:"-,"` // named "-"
67 String4 string `json:"string4,omitempty"` // renamed, ignore if empty
68 String5 string `json:","` // no-op
69 String6 string `json:",omitempty"` // ignore if empty
70 }
71
72 type TjsontagsBool struct {
73 Bool1 bool `json:"bool1"` // renamed
74 Bool2 bool `json:"-"` // ignored
75 Bool3 bool `json:"-,"` // named "-"
76 Bool4 bool `json:"bool4,omitempty"` // renamed, ignore if empty
77 Bool5 bool `json:","` // no-op
78 Bool6 bool `json:",omitempty"` // ignore if empty
79 }
80
81 type TjsontagsInt struct {
82 Int1 int `json:"int1"` // renamed
83 Int2 int `json:"-"` // ignored
84 Int3 int `json:"-,"` // named "-"
85 Int4 int `json:"int4,omitempty"` // renamed, ignore if empty
86 Int5 int `json:","` // no-op
87 Int6 int `json:",omitempty"` // ignore if empty
88 }
89
90 type TjsontagsUint struct {
91 Uint1 uint `json:"uint1"` // renamed
92 Uint2 uint `json:"-"` // ignored
93 Uint3 uint `json:"-,"` // named "-"
94 Uint4 uint `json:"uint4,omitempty"` // renamed, ignore if empty
95 Uint5 uint `json:","` // no-op
96 Uint6 uint `json:",omitempty"` // ignore if empty
97 }
98
99 type TjsontagsFloat struct {
100 Float1 float64 `json:"float1"` // renamed
101 Float2 float64 `json:"-"` // ignored
102 Float3 float64 `json:"-,"` // named "-"
103 Float4 float64 `json:"float4,omitempty"` // renamed, ignore if empty
104 Float5 float64 `json:","` // no-op
105 Float6 float64 `json:",omitempty"` // ignore if empty
106 }
107
108 type TjsontagsComplex struct {
109 Complex1 complex128 `json:"complex1"` // renamed
110 Complex2 complex128 `json:"-"` // ignored
111 Complex3 complex128 `json:"-,"` // named "-"
112 Complex4 complex128 `json:"complex4,omitempty"` // renamed, ignore if empty
113 Complex5 complex128 `json:","` // no-op
114 Complex6 complex128 `json:",omitempty"` // ignore if empty
115 }
116
117 type TjsontagsPtr struct {
118 Ptr1 *string `json:"ptr1"` // renamed
119 Ptr2 *string `json:"-"` // ignored
120 Ptr3 *string `json:"-,"` // named "-"
121 Ptr4 *string `json:"ptr4,omitempty"` // renamed, ignore if empty
122 Ptr5 *string `json:","` // no-op
123 Ptr6 *string `json:",omitempty"` // ignore if empty
124 }
125
126 type TjsontagsArray struct {
127 Array1 [2]string `json:"array1"` // renamed
128 Array2 [2]string `json:"-"` // ignored
129 Array3 [2]string `json:"-,"` // named "-"
130 Array4 [2]string `json:"array4,omitempty"` // renamed, ignore if empty
131 Array5 [2]string `json:","` // no-op
132 Array6 [2]string `json:",omitempty"` // ignore if empty
133 }
134
135 type TjsontagsSlice struct {
136 Slice1 []string `json:"slice1"` // renamed
137 Slice2 []string `json:"-"` // ignored
138 Slice3 []string `json:"-,"` // named "-"
139 Slice4 []string `json:"slice4,omitempty"` // renamed, ignore if empty
140 Slice5 []string `json:","` // no-op
141 Slice6 []string `json:",omitempty"` // ignore if empty
142 }
143
144 type TjsontagsMap struct {
145 Map1 map[string]string `json:"map1"` // renamed
146 Map2 map[string]string `json:"-"` // ignored
147 Map3 map[string]string `json:"-,"` // named "-"
148 Map4 map[string]string `json:"map4,omitempty"` // renamed, ignore if empty
149 Map5 map[string]string `json:","` // no-op
150 Map6 map[string]string `json:",omitempty"` // ignore if empty
151 }
152
63153 func TestPretty(t *testing.T) {
154 // used below
155 newStr := func(s string) *string {
156 return &s
157 }
158
64159 cases := []struct {
65160 val interface{}
66161 exp string // used in cases where JSON can't handle it
175270 val: fmt.Errorf("error"),
176271 exp: `"error"`,
177272 },
273 {
274 val: TjsontagsString{
275 String1: "v1",
276 String2: "v2",
277 String3: "v3",
278 String4: "v4",
279 String5: "v5",
280 String6: "v6",
281 },
282 },
283 {val: TjsontagsString{}},
284 {
285 val: TjsontagsBool{
286 Bool1: true,
287 Bool2: true,
288 Bool3: true,
289 Bool4: true,
290 Bool5: true,
291 Bool6: true,
292 },
293 },
294 {val: TjsontagsBool{}},
295 {
296 val: TjsontagsInt{
297 Int1: 1,
298 Int2: 2,
299 Int3: 3,
300 Int4: 4,
301 Int5: 5,
302 Int6: 6,
303 },
304 },
305 {val: TjsontagsInt{}},
306 {
307 val: TjsontagsUint{
308 Uint1: 1,
309 Uint2: 2,
310 Uint3: 3,
311 Uint4: 4,
312 Uint5: 5,
313 Uint6: 6,
314 },
315 },
316 {val: TjsontagsUint{}},
317 {
318 val: TjsontagsFloat{
319 Float1: 1.1,
320 Float2: 2.2,
321 Float3: 3.3,
322 Float4: 4.4,
323 Float5: 5.5,
324 Float6: 6.6,
325 },
326 },
327 {val: TjsontagsFloat{}},
328 {
329 val: TjsontagsComplex{
330 Complex1: 1i,
331 Complex2: 2i,
332 Complex3: 3i,
333 Complex4: 4i,
334 Complex5: 5i,
335 Complex6: 6i,
336 },
337 exp: `{"complex1":"(0+1i)","-":"(0+3i)","complex4":"(0+4i)","Complex5":"(0+5i)","Complex6":"(0+6i)"}`,
338 },
339 {
340 val: TjsontagsComplex{},
341 exp: `{"complex1":"(0+0i)","-":"(0+0i)","Complex5":"(0+0i)"}`,
342 },
343 {
344 val: TjsontagsPtr{
345 Ptr1: newStr("1"),
346 Ptr2: newStr("2"),
347 Ptr3: newStr("3"),
348 Ptr4: newStr("4"),
349 Ptr5: newStr("5"),
350 Ptr6: newStr("6"),
351 },
352 },
353 {val: TjsontagsPtr{}},
354 {
355 val: TjsontagsArray{
356 Array1: [2]string{"v1", "v1"},
357 Array2: [2]string{"v2", "v2"},
358 Array3: [2]string{"v3", "v3"},
359 Array4: [2]string{"v4", "v4"},
360 Array5: [2]string{"v5", "v5"},
361 Array6: [2]string{"v6", "v6"},
362 },
363 },
364 {val: TjsontagsArray{}},
365 {
366 val: TjsontagsSlice{
367 Slice1: []string{"v1", "v1"},
368 Slice2: []string{"v2", "v2"},
369 Slice3: []string{"v3", "v3"},
370 Slice4: []string{"v4", "v4"},
371 Slice5: []string{"v5", "v5"},
372 Slice6: []string{"v6", "v6"},
373 },
374 },
375 {
376 val: TjsontagsSlice{},
377 exp: `{"slice1":[],"-":[],"Slice5":[]}`,
378 },
379 {
380 val: TjsontagsMap{
381 Map1: map[string]string{"k1": "v1"},
382 Map2: map[string]string{"k2": "v2"},
383 Map3: map[string]string{"k3": "v3"},
384 Map4: map[string]string{"k4": "v4"},
385 Map5: map[string]string{"k5": "v5"},
386 Map6: map[string]string{"k6": "v6"},
387 },
388 },
389 {
390 val: TjsontagsMap{},
391 exp: `{"map1":{},"-":{},"Map5":{}}`,
392 },
178393 }
179394
180395 f := NewFormatter(Options{})
191406 want = string(jb)
192407 }
193408 if ours != want {
194 t.Errorf("[%d]: expected %q, got %q", i, want, ours)
409 t.Errorf("[%d]:\n\texpected %q\n\tgot %q", i, want, ours)
195410 }
196411 }
197412 }