From dd7530dea941307d0f7fd054d6ae14d0e49b0650 Mon Sep 17 00:00:00 2001 From: Leonid Shevtsov Date: Tue, 10 Sep 2024 18:18:19 +0300 Subject: [PATCH] Fix panic on empty interface field --- devslog.go | 8 ++++++-- devslog_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/devslog.go b/devslog.go index 9622792..e12e039 100644 --- a/devslog.go +++ b/devslog.go @@ -599,8 +599,12 @@ func (h *developHandler) elementType(t reflect.Type, v reflect.Value, l int, p i } } case reflect.Interface: - v = reflect.ValueOf(v.Interface()) - b = h.elementType(v.Type(), v, l, p) + if v.IsZero() { + b = nilString() + } else { + v = reflect.ValueOf(v.Interface()) + b = h.elementType(v.Type(), v, l, p) + } default: b = atb("Unknown type: ") b = append(b, atb(v.Kind())...) diff --git a/devslog_test.go b/devslog_test.go index f1a9e23..cc21a00 100644 --- a/devslog_test.go +++ b/devslog_test.go @@ -71,6 +71,7 @@ func Test_Types(t *testing.T) { test_MapOfPointers(t, opts) test_MapOfInterface(t, opts) test_Struct(t, opts) + test_NilInterface(t, opts) test_Group(t, opts) test_LogValuer(t, opts) test_LogValuerPanic(t, opts) @@ -734,6 +735,29 @@ func test_Struct(t *testing.T, o *Options) { } } +func test_NilInterface(t *testing.T, o *Options) { + w := &MockWriter{} + logger := slog.New(NewHandler(w, o)) + + type StructWithInterface struct { + Data any + } + + s := StructWithInterface{} + + logger.Info("msg", + slog.Any("s", s), + ) + + expected := []byte( + "\x1b[2m\x1b[37m[]\x1b[0m \x1b[42m\x1b[30m INFO \x1b[0m \x1b[32mmsg\x1b[0m\n\x1b[33mS\x1b[0m \x1b[35ms\x1b[0m: \x1b[33md\x1b[0m\x1b[33me\x1b[0m\x1b[33mv\x1b[0m\x1b[33ms\x1b[0m\x1b[33ml\x1b[0m\x1b[33mo\x1b[0m\x1b[33mg\x1b[0m\x1b[33m.\x1b[0m\x1b[33mS\x1b[0m\x1b[33mt\x1b[0m\x1b[33mr\x1b[0m\x1b[33mu\x1b[0m\x1b[33mc\x1b[0m\x1b[33mt\x1b[0m\x1b[33mW\x1b[0m\x1b[33mi\x1b[0m\x1b[33mt\x1b[0m\x1b[33mh\x1b[0m\x1b[33mI\x1b[0m\x1b[33mn\x1b[0m\x1b[33mt\x1b[0m\x1b[33me\x1b[0m\x1b[33mr\x1b[0m\x1b[33mf\x1b[0m\x1b[33ma\x1b[0m\x1b[33mc\x1b[0m\x1b[33me\x1b[0m\n \x1b[32mData\x1b[0m: \x1b[31m<\x1b[0m\x1b[33mnil\x1b[0m\x1b[31m>\x1b[0m\n\n", + ) + + if !bytes.Equal(w.WrittenData, expected) { + t.Errorf("\nExpected:\n%s\nGot:\n%s\nExpected:\n%[1]q\nGot:\n%[2]q", expected, w.WrittenData) + } +} + func test_Group(t *testing.T, o *Options) { w := &MockWriter{} logger := slog.New(NewHandler(w, o))