Skip to content

Commit c80afc3

Browse files
committed
fmt: fix incorrect format of whole-number floats when using %#v
This fixes the unwanted behaviour where printing a zero float with the #v fmt verb outputs "0" - e.g. missing the trailing decimal. This means that the output would be interpreted as an int rather than a float when parsed as Go source. After this change the the output is "0.0". Fixes #26363
1 parent 8a33045 commit c80afc3

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

src/fmt/fmt_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,14 @@ var fmtTests = []struct {
690690
{"%#v", []int32(nil), "[]int32(nil)"},
691691
{"%#v", 1.2345678, "1.2345678"},
692692
{"%#v", float32(1.2345678), "1.2345678"},
693+
694+
// Whole number floats should have a single trailing zero added, but not
695+
// for exponent notation.
696+
{"%#v", 1.0, "1.0"},
697+
{"%#v", 1000000.0, "1e+06"},
698+
{"%#v", float32(1.0), "1.0"},
699+
{"%#v", float32(1000000.0), "1e+06"},
700+
693701
// Only print []byte and []uint8 as type []byte if they appear at the top level.
694702
{"%#v", []byte(nil), "[]byte(nil)"},
695703
{"%#v", []uint8(nil), "[]byte(nil)"},

src/fmt/format.go

+26-15
Original file line numberDiff line numberDiff line change
@@ -481,15 +481,19 @@ func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
481481
return
482482
}
483483
// The sharp flag forces printing a decimal point for non-binary formats
484-
// and retains trailing zeros, which we may need to restore.
485-
if f.sharp && verb != 'b' {
484+
// and retains trailing zeros, which we may need to restore. For the sharpV
485+
// flag, we ensure a single trailing zero is present if the output is not
486+
// in exponent notation.
487+
if f.sharpV || (f.sharp && verb != 'b') {
486488
digits := 0
487-
switch verb {
488-
case 'v', 'g', 'G':
489-
digits = prec
490-
// If no precision is set explicitly use a precision of 6.
491-
if digits == -1 {
492-
digits = 6
489+
if !f.sharpV {
490+
switch verb {
491+
case 'g', 'G':
492+
digits = prec
493+
// If no precision is set explicitly use a precision of 6.
494+
if digits == -1 {
495+
digits = 6
496+
}
493497
}
494498
}
495499

@@ -498,25 +502,32 @@ func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
498502
var tailBuf [5]byte
499503
tail := tailBuf[:0]
500504

501-
hasDecimalPoint := false
505+
var hasDecimalPoint, hasExponent bool
502506
// Starting from i = 1 to skip sign at num[0].
503507
for i := 1; i < len(num); i++ {
504508
switch num[i] {
505509
case '.':
506510
hasDecimalPoint = true
507511
case 'e', 'E':
512+
hasExponent = true
508513
tail = append(tail, num[i:]...)
509514
num = num[:i]
510515
default:
511516
digits--
512517
}
513518
}
514-
if !hasDecimalPoint {
515-
num = append(num, '.')
516-
}
517-
for digits > 0 {
518-
num = append(num, '0')
519-
digits--
519+
if f.sharpV {
520+
if !hasDecimalPoint && !hasExponent {
521+
num = append(num, '.', '0')
522+
}
523+
} else {
524+
if !hasDecimalPoint {
525+
num = append(num, '.')
526+
}
527+
for digits > 0 {
528+
num = append(num, '0')
529+
digits--
530+
}
520531
}
521532
num = append(num, tail...)
522533
}

0 commit comments

Comments
 (0)