Skip to content

Commit

Permalink
fmt: display contained values when formatting atomic booleans and int…
Browse files Browse the repository at this point in the history
…egers

* treat `atomic.{Int32,Int64,Uint32,Uint64}` values as integers when
  formatting, using the underlying integer value (by calling Load). This
  has the effect of, for example, formatting an atomic integer type
  containing 42 as "42", not "{{}, 42}").

* treat `atomic.Bool` values as booleans when formatting, using the
  contained boolean value (by calling Load). This has the effect of, for
  example, formatting an true atomic.Bool value containing as "true",
  not "{{}, 1}" or "{{} %!t(uint32=1)}" as before.

Fixes golang#54731
  • Loading branch information
jpwnetcraft committed Aug 29, 2022
1 parent 7393049 commit 0480723
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/fmt/fmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"reflect"
"runtime"
"strings"
"sync/atomic"
"testing"
"time"
"unicode"
Expand All @@ -39,6 +40,36 @@ type (
renamedComplex128 complex128
)

func newAtomicInt32(val int32) *atomic.Int32 {
var r atomic.Int32
r.Store(val)
return &r
}

func newAtomicUint32(val uint32) *atomic.Uint32 {
var r atomic.Uint32
r.Store(val)
return &r
}

func newAtomicInt64(val int64) *atomic.Int64 {
var r atomic.Int64
r.Store(val)
return &r
}

func newAtomicUint64(val uint64) *atomic.Uint64 {
var r atomic.Uint64
r.Store(val)
return &r
}

func newAtomicBool(val bool) *atomic.Bool {
var r atomic.Bool
r.Store(val)
return &r
}

func TestFmtInterface(t *testing.T) {
var i1 any
i1 = "abc"
Expand Down Expand Up @@ -1081,6 +1112,32 @@ var fmtTests = []struct {
{"%☠", SI{&[]any{I(1), G(2)}}, "{%!☠(*[]interface {}=&[1 2])}"},
{"%☠", reflect.Value{}, "<invalid reflect.Value>"},
{"%☠", map[float64]int{NaN: 1}, "map[%!☠(float64=NaN):%!☠(int=1)]"},

// atomics
{"%d", newAtomicInt32(25), "25"},
{"%d", newAtomicInt32(math.MaxInt32), "2147483647"},
{"%d", newAtomicInt32(-5), "-5"},
{"%d", newAtomicInt32(math.MinInt32), "-2147483648"},

{"%d", newAtomicUint32(19), "19"},
{"%d", newAtomicUint32(math.MaxUint32), "4294967295"},

{"%d", newAtomicInt64(99), "99"},
{"%d", newAtomicInt64(math.MaxInt64), "9223372036854775807"},
{"%d", newAtomicInt64(-7), "-7"},
{"%d", newAtomicInt64(math.MinInt64), "-9223372036854775808"},

{"%d", newAtomicUint64(12), "12"},
{"%d", newAtomicUint64(math.MaxUint64), "18446744073709551615"},

{"%t", newAtomicBool(true), "true"},
{"%t", newAtomicBool(false), "false"},

{"%v", newAtomicInt32(42), "42"},
{"%v", newAtomicUint32(4242), "4242"},
{"%v", newAtomicInt64(424242), "424242"},
{"%v", newAtomicUint64(42424242), "42424242"},
{"%v", newAtomicBool(true), "true"},
}

// zeroFill generates zero-filled strings of the specified width. The length
Expand Down
21 changes: 21 additions & 0 deletions src/fmt/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"reflect"
"strconv"
"sync"
"sync/atomic"
"unicode/utf8"
)

Expand Down Expand Up @@ -747,6 +748,26 @@ func (p *pp) printArg(arg any, verb rune) {
p.fmtInteger(f, unsigned, verb)
case uintptr:
p.fmtInteger(uint64(f), unsigned, verb)
case atomic.Int32:
p.fmtInteger(uint64(f.Load()), signed, verb)
case *atomic.Int32:
p.fmtInteger(uint64(f.Load()), signed, verb)
case atomic.Int64:
p.fmtInteger(uint64(f.Load()), signed, verb)
case *atomic.Int64:
p.fmtInteger(uint64(f.Load()), signed, verb)
case atomic.Uint32:
p.fmtInteger(uint64(f.Load()), unsigned, verb)
case *atomic.Uint32:
p.fmtInteger(uint64(f.Load()), unsigned, verb)
case atomic.Uint64:
p.fmtInteger(uint64(f.Load()), unsigned, verb)
case *atomic.Uint64:
p.fmtInteger(uint64(f.Load()), unsigned, verb)
case atomic.Bool:
p.fmtBool(f.Load(), verb)
case *atomic.Bool:
p.fmtBool(f.Load(), verb)
case string:
p.fmtString(f, verb)
case []byte:
Expand Down

0 comments on commit 0480723

Please sign in to comment.