Skip to content

Commit

Permalink
fmt: fix incorrect format of whole-number floats when using %#v
Browse files Browse the repository at this point in the history
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

Change-Id: Ic5c060522459cd5ce077675d47c848b22ddc34fa
GitHub-Last-Rev: adfb061
GitHub-Pull-Request: #26383
Reviewed-on: https://go-review.googlesource.com/123956
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Reviewed-by: Rob Pike <r@golang.org>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
  • Loading branch information
dave authored and robpike committed Aug 28, 2018
1 parent cb7f9ec commit 7c7cecc
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
8 changes: 8 additions & 0 deletions src/fmt/fmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,14 @@ var fmtTests = []struct {
{"%#v", []int32(nil), "[]int32(nil)"},
{"%#v", 1.2345678, "1.2345678"},
{"%#v", float32(1.2345678), "1.2345678"},

// Whole number floats should have a single trailing zero added, but not
// for exponent notation.
{"%#v", 1.0, "1.0"},
{"%#v", 1000000.0, "1e+06"},
{"%#v", float32(1.0), "1.0"},
{"%#v", float32(1000000.0), "1e+06"},

// Only print []byte and []uint8 as type []byte if they appear at the top level.
{"%#v", []byte(nil), "[]byte(nil)"},
{"%#v", []uint8(nil), "[]byte(nil)"},
Expand Down
41 changes: 26 additions & 15 deletions src/fmt/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,15 +481,19 @@ func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
return
}
// The sharp flag forces printing a decimal point for non-binary formats
// and retains trailing zeros, which we may need to restore.
if f.sharp && verb != 'b' {
// and retains trailing zeros, which we may need to restore. For the sharpV
// flag, we ensure a single trailing zero is present if the output is not
// in exponent notation.
if f.sharpV || (f.sharp && verb != 'b') {
digits := 0
switch verb {
case 'v', 'g', 'G':
digits = prec
// If no precision is set explicitly use a precision of 6.
if digits == -1 {
digits = 6
if !f.sharpV {
switch verb {
case 'g', 'G':
digits = prec
// If no precision is set explicitly use a precision of 6.
if digits == -1 {
digits = 6
}
}
}

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

hasDecimalPoint := false
var hasDecimalPoint, hasExponent bool
// Starting from i = 1 to skip sign at num[0].
for i := 1; i < len(num); i++ {
switch num[i] {
case '.':
hasDecimalPoint = true
case 'e', 'E':
hasExponent = true
tail = append(tail, num[i:]...)
num = num[:i]
default:
digits--
}
}
if !hasDecimalPoint {
num = append(num, '.')
}
for digits > 0 {
num = append(num, '0')
digits--
if f.sharpV {
if !hasDecimalPoint && !hasExponent {
num = append(num, '.', '0')
}
} else {
if !hasDecimalPoint {
num = append(num, '.')
}
for digits > 0 {
num = append(num, '0')
digits--
}
}
num = append(num, tail...)
}
Expand Down
8 changes: 4 additions & 4 deletions test/switch5.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ func f0(x int) {
func f1(x float32) {
switch x {
case 5:
case 5: // ERROR "duplicate case 5 in switch"
case 5.0: // ERROR "duplicate case 5 in switch"
case 5: // ERROR "duplicate case 5 .value 5\.0. in switch"
case 5.0: // ERROR "duplicate case 5 .value 5\.0. in switch"
}
}

Expand All @@ -44,9 +44,9 @@ func f3(e interface{}) {
case 0: // ERROR "duplicate case 0 in switch"
case int64(0):
case float32(10):
case float32(10): // ERROR "duplicate case float32\(10\) .value 10. in switch"
case float32(10): // ERROR "duplicate case float32\(10\) .value 10\.0. in switch"
case float64(10):
case float64(10): // ERROR "duplicate case float64\(10\) .value 10. in switch"
case float64(10): // ERROR "duplicate case float64\(10\) .value 10\.0. in switch"
}
}

Expand Down

0 comments on commit 7c7cecc

Please sign in to comment.