File tree Expand file tree Collapse file tree 2 files changed +46
-2
lines changed Expand file tree Collapse file tree 2 files changed +46
-2
lines changed Original file line number Diff line number Diff line change @@ -27,6 +27,7 @@ package attributes
2727
2828import (
2929 "fmt"
30+ "reflect"
3031 "strings"
3132)
3233
@@ -121,8 +122,26 @@ func (a *Attributes) String() string {
121122 return sb .String ()
122123}
123124
124- func str (x any ) string {
125- if v , ok := x .(fmt.Stringer ); ok {
125+ func str (x any ) (s string ) {
126+ defer func () {
127+ if r := recover (); r != nil {
128+ // If it panics with a nil pointer, just say "<nil>". The likeliest causes are a
129+ // [fmt.Stringer] that fails to guard against nil or a nil pointer for a
130+ // value receiver, and in either case, "<nil>" is a nice result.
131+ //
132+ // Adapted from the code in fmt/print.go.
133+ if v := reflect .ValueOf (x ); v .Kind () == reflect .Pointer && v .IsNil () {
134+ s = "<nil>"
135+ return
136+ }
137+
138+ // The panic was likely not caused by fmt.Stringer.
139+ panic (r )
140+ }
141+ }()
142+ if x == nil {
143+ return "<nil>"
144+ } else if v , ok := x .(fmt.Stringer ); ok {
126145 return v .String ()
127146 } else if v , ok := x .(string ); ok {
128147 return v
Original file line number Diff line number Diff line change @@ -29,6 +29,10 @@ type stringVal struct {
2929 s string
3030}
3131
32+ func (s stringVal ) String () string {
33+ return s .s
34+ }
35+
3236func (s stringVal ) Equal (o any ) bool {
3337 os , ok := o .(stringVal )
3438 return ok && s .s == os .s
@@ -57,6 +61,27 @@ func ExampleAttributes_WithValue() {
5761 // Key two: {two}
5862}
5963
64+ func ExampleString () {
65+ type keyOne struct {}
66+ type keyTwo struct {}
67+ type keyThree struct {}
68+ type keyFour struct {}
69+ a1 := attributes .New (keyOne {}, nil ) // untyped nil
70+ a2 := attributes .New (keyTwo {}, (* stringVal )(nil )) // typed nil
71+ a3 := attributes .New (keyThree {}, 1 )
72+ a4 := attributes .New (keyFour {}, stringVal {s : "two" })
73+ fmt .Println ("a1:" , a1 .String ())
74+ fmt .Println ("a2:" , a2 .String ())
75+ fmt .Println ("a3:" , a3 .String ())
76+ fmt .Println ("a4:" , a4 .String ())
77+
78+ // Output:
79+ // a1: {"<%!p(attributes_test.keyOne={})>": "<nil>" }
80+ // a2: {"<%!p(attributes_test.keyTwo={})>": "<nil>" }
81+ // a3: {"<%!p(attributes_test.keyThree={})>": "<%!p(int=1)>" }
82+ // a4: {"<%!p(attributes_test.keyFour={})>": "two" }
83+ }
84+
6085// Test that two attributes with the same content are Equal.
6186func TestEqual (t * testing.T ) {
6287 type keyOne struct {}
You can’t perform that action at this time.
0 commit comments