diff --git a/klog.go b/klog.go index 6b842d8c..dacdf911 100644 --- a/klog.go +++ b/klog.go @@ -847,7 +847,7 @@ func kvListFormat(b *bytes.Buffer, keysAndValues ...interface{}) { // (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235). switch v := v.(type) { case fmt.Stringer: - writeStringValue(b, true, v.String()) + writeStringValue(b, true, stringerToString(v)) case string: writeStringValue(b, true, v) case error: @@ -872,6 +872,16 @@ func kvListFormat(b *bytes.Buffer, keysAndValues ...interface{}) { } } +func stringerToString(s fmt.Stringer) (ret string) { + defer func() { + if err := recover(); err != nil { + ret = "nil" + } + }() + ret = s.String() + return +} + func writeStringValue(b *bytes.Buffer, quote bool, v string) { data := []byte(v) index := bytes.IndexByte(data, '\n') diff --git a/klog_test.go b/klog_test.go index a89968ad..a371845d 100644 --- a/klog_test.go +++ b/klog_test.go @@ -1063,8 +1063,20 @@ func TestErrorS(t *testing.T) { } } +// point conforms to fmt.Stringer interface as it implements the String() method +type point struct { + x int + y int +} + +// we now have a value receiver +func (p point) String() string { + return fmt.Sprintf("x=%d, y=%d", p.x, p.y) +} + // Test that kvListFormat works as advertised. func TestKvListFormat(t *testing.T) { + var emptyPoint *point var testKVList = []struct { keysValues []interface{} want string @@ -1159,6 +1171,10 @@ No whitespace.`, })}, want: " pods=[kube-system/kube-dns mi-conf]", }, + { + keysValues: []interface{}{"point-1", point{100, 200}, "point-2", emptyPoint}, + want: " point-1=\"x=100, y=200\" point-2=\"nil\"", + }, } for _, d := range testKVList {