mirror of
https://github.com/golang/go
synced 2024-11-24 05:10:19 -07:00
fmt.Print*: reimplement to switch on type first.
This shortens, simplifies and regularizes the code significantly. (Improvements to reflect could make another step.) Passes all.bash. One semantic change occurs: The String() method changes behavior. It used to run only for string formats such as %s and %q. Instead, it now runs whenever the item has the method and the result is then processed by the format as a string. Besides the regularization, this has three effects: 1) width is honored for String() items 2) %x works for String() items 3) implementations of String that merely recur will recur forever Regarding point 3, example from the updated documentation: type X int func (x X) String() string { return Sprintf("%d", x) } should cast the value before recurring: func (x X) String() string { return Sprintf("%d", int(x)) } R=rsc CC=golang-dev https://golang.org/cl/1613045
This commit is contained in:
parent
43b3a247d3
commit
d482c163be
@ -13,6 +13,29 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type (
|
||||
renamedBool bool
|
||||
renamedInt int
|
||||
renamedInt8 int8
|
||||
renamedInt16 int16
|
||||
renamedInt32 int32
|
||||
renamedInt64 int64
|
||||
renamedUint uint
|
||||
renamedUint8 uint8
|
||||
renamedUint16 uint16
|
||||
renamedUint32 uint32
|
||||
renamedUint64 uint64
|
||||
renamedUintptr uintptr
|
||||
renamedString string
|
||||
renamedBytes []byte
|
||||
renamedFloat float
|
||||
renamedFloat32 float32
|
||||
renamedFloat64 float64
|
||||
renamedComplex complex
|
||||
renamedComplex64 complex64
|
||||
renamedComplex128 complex128
|
||||
)
|
||||
|
||||
func TestFmtInterface(t *testing.T) {
|
||||
var i1 interface{}
|
||||
i1 = "abc"
|
||||
@ -43,7 +66,7 @@ type A struct {
|
||||
|
||||
type I int
|
||||
|
||||
func (i I) String() string { return Sprintf("<%d>", i) }
|
||||
func (i I) String() string { return Sprintf("<%d>", int(i)) }
|
||||
|
||||
type B struct {
|
||||
i I
|
||||
@ -58,6 +81,10 @@ type C struct {
|
||||
var b byte
|
||||
|
||||
var fmttests = []fmtTest{
|
||||
fmtTest{"%d", 12345, "12345"},
|
||||
fmtTest{"%v", 12345, "12345"},
|
||||
fmtTest{"%t", true, "true"},
|
||||
|
||||
// basic string
|
||||
fmtTest{"%s", "abc", "abc"},
|
||||
fmtTest{"%x", "abc", "616263"},
|
||||
@ -245,7 +272,10 @@ var fmttests = []fmtTest{
|
||||
fmtTest{"%+v", C{1, B{2, 3}}, `{i:1 B:{i:<2> j:3}}`},
|
||||
|
||||
// q on Stringable items
|
||||
fmtTest{"%s", I(23), `<23>`},
|
||||
fmtTest{"%q", I(23), `"<23>"`},
|
||||
fmtTest{"%x", I(23), `3c32333e`},
|
||||
fmtTest{"%d", I(23), `%d(string=<23>)`},
|
||||
|
||||
// %p on non-pointers
|
||||
fmtTest{"%p", make(chan int), "PTR"},
|
||||
@ -260,6 +290,30 @@ var fmttests = []fmtTest{
|
||||
fmtTest{"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
|
||||
fmtTest{"%#v", 1000000000, "1000000000"},
|
||||
|
||||
// renamings
|
||||
fmtTest{"%v", renamedBool(true), "true"},
|
||||
fmtTest{"%d", renamedBool(true), "%d(fmt_test.renamedBool=true)"},
|
||||
fmtTest{"%o", renamedInt(8), "10"},
|
||||
fmtTest{"%d", renamedInt8(-9), "-9"},
|
||||
fmtTest{"%v", renamedInt16(10), "10"},
|
||||
fmtTest{"%v", renamedInt32(-11), "-11"},
|
||||
fmtTest{"%X", renamedInt64(255), "FF"},
|
||||
fmtTest{"%v", renamedUint(13), "13"},
|
||||
fmtTest{"%o", renamedUint8(14), "16"},
|
||||
fmtTest{"%X", renamedUint16(15), "F"},
|
||||
fmtTest{"%d", renamedUint32(16), "16"},
|
||||
fmtTest{"%X", renamedUint64(17), "11"},
|
||||
fmtTest{"%o", renamedUintptr(18), "22"},
|
||||
fmtTest{"%x", renamedString("thing"), "7468696e67"},
|
||||
// TODO: It would be nice if this one worked, but it's hard.
|
||||
// fmtTest{"%q", renamedBytes([]byte("hello")), `"hello"`},
|
||||
fmtTest{"%v", renamedFloat(11), "11"},
|
||||
fmtTest{"%v", renamedFloat32(22), "22"},
|
||||
fmtTest{"%v", renamedFloat64(33), "33"},
|
||||
fmtTest{"%v", renamedComplex(7 + .2i), "(7+0.2i)"},
|
||||
fmtTest{"%v", renamedComplex64(3 + 4i), "(3+4i)"},
|
||||
fmtTest{"%v", renamedComplex128(4 - 3i), "(4-3i)"},
|
||||
|
||||
// erroneous things
|
||||
fmtTest{"%d", "hello", "%d(string=hello)"},
|
||||
fmtTest{"no args", "hello", "no args?(extra string=hello)"},
|
||||
|
@ -234,87 +234,6 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
|
||||
f.pad(buf[i:])
|
||||
}
|
||||
|
||||
// fmt_d64 formats an int64 in decimal.
|
||||
func (f *fmt) fmt_d64(v int64) { f.integer(v, 10, signed, ldigits) }
|
||||
|
||||
// fmt_d32 formats an int32 in decimal.
|
||||
func (f *fmt) fmt_d32(v int32) { f.integer(int64(v), 10, signed, ldigits) }
|
||||
|
||||
// fmt_d formats an int in decimal.
|
||||
func (f *fmt) fmt_d(v int) { f.integer(int64(v), 10, signed, ldigits) }
|
||||
|
||||
// fmt_ud64 formats a uint64 in decimal.
|
||||
func (f *fmt) fmt_ud64(v uint64) { f.integer(int64(v), 10, unsigned, ldigits) }
|
||||
|
||||
// fmt_ud32 formats a uint32 in decimal.
|
||||
func (f *fmt) fmt_ud32(v uint32) { f.integer(int64(v), 10, unsigned, ldigits) }
|
||||
|
||||
// fmt_ud formats a uint in decimal.
|
||||
func (f *fmt) fmt_ud(v uint) { f.integer(int64(v), 10, unsigned, ldigits) }
|
||||
|
||||
// fmt_x64 formats an int64 in hexadecimal.
|
||||
func (f *fmt) fmt_x64(v int64) { f.integer(v, 16, signed, ldigits) }
|
||||
|
||||
// fmt_x32 formats an int32 in hexadecimal.
|
||||
func (f *fmt) fmt_x32(v int32) { f.integer(int64(v), 16, signed, ldigits) }
|
||||
|
||||
// fmt_x formats an int in hexadecimal.
|
||||
func (f *fmt) fmt_x(v int) { f.integer(int64(v), 16, signed, ldigits) }
|
||||
|
||||
// fmt_ux64 formats a uint64 in hexadecimal.
|
||||
func (f *fmt) fmt_ux64(v uint64) { f.integer(int64(v), 16, unsigned, ldigits) }
|
||||
|
||||
// fmt_ux32 formats a uint32 in hexadecimal.
|
||||
func (f *fmt) fmt_ux32(v uint32) { f.integer(int64(v), 16, unsigned, ldigits) }
|
||||
|
||||
// fmt_ux formats a uint in hexadecimal.
|
||||
func (f *fmt) fmt_ux(v uint) { f.integer(int64(v), 16, unsigned, ldigits) }
|
||||
|
||||
// fmt_X64 formats an int64 in upper case hexadecimal.
|
||||
func (f *fmt) fmt_X64(v int64) { f.integer(v, 16, signed, udigits) }
|
||||
|
||||
// fmt_X32 formats an int32 in upper case hexadecimal.
|
||||
func (f *fmt) fmt_X32(v int32) { f.integer(int64(v), 16, signed, udigits) }
|
||||
|
||||
// fmt_X formats an int in upper case hexadecimal.
|
||||
func (f *fmt) fmt_X(v int) { f.integer(int64(v), 16, signed, udigits) }
|
||||
|
||||
// fmt_uX64 formats a uint64 in upper case hexadecimal.
|
||||
func (f *fmt) fmt_uX64(v uint64) { f.integer(int64(v), 16, unsigned, udigits) }
|
||||
|
||||
// fmt_uX32 formats a uint32 in upper case hexadecimal.
|
||||
func (f *fmt) fmt_uX32(v uint32) { f.integer(int64(v), 16, unsigned, udigits) }
|
||||
|
||||
// fmt_uX formats a uint in upper case hexadecimal.
|
||||
func (f *fmt) fmt_uX(v uint) { f.integer(int64(v), 16, unsigned, udigits) }
|
||||
|
||||
// fmt_o64 formats an int64 in octal.
|
||||
func (f *fmt) fmt_o64(v int64) { f.integer(v, 8, signed, ldigits) }
|
||||
|
||||
// fmt_o32 formats an int32 in octal.
|
||||
func (f *fmt) fmt_o32(v int32) { f.integer(int64(v), 8, signed, ldigits) }
|
||||
|
||||
// fmt_o formats an int in octal.
|
||||
func (f *fmt) fmt_o(v int) { f.integer(int64(v), 8, signed, ldigits) }
|
||||
|
||||
// fmt_uo64 formats a uint64 in octal.
|
||||
func (f *fmt) fmt_uo64(v uint64) { f.integer(int64(v), 8, unsigned, ldigits) }
|
||||
|
||||
// fmt_uo32 formats a uint32 in octal.
|
||||
func (f *fmt) fmt_uo32(v uint32) { f.integer(int64(v), 8, unsigned, ldigits) }
|
||||
|
||||
// fmt_uo formats a uint in octal.
|
||||
func (f *fmt) fmt_uo(v uint) { f.integer(int64(v), 8, unsigned, ldigits) }
|
||||
|
||||
// fmt_b64 formats an int64 in binary.
|
||||
func (f *fmt) fmt_b64(v int64) { f.integer(v, 2, signed, ldigits) }
|
||||
|
||||
// fmt_ub64 formats a uint64 in binary.
|
||||
func (f *fmt) fmt_ub64(v uint64) { f.integer(int64(v), 2, unsigned, ldigits) }
|
||||
|
||||
// fmt_c formats a Unicode character.
|
||||
func (f *fmt) fmt_c(v int) { f.padString(string(v)) }
|
||||
|
||||
// fmt_s formats a string.
|
||||
func (f *fmt) fmt_s(s string) {
|
||||
if f.precPresent {
|
||||
@ -422,14 +341,13 @@ func (f *fmt) fmt_G32(v float32) { f.plusSpace(strconv.Ftoa32(v, 'G', doPrec(f,
|
||||
// fmt_fb32 formats a float32 in the form -123p3 (exponent is power of 2).
|
||||
func (f *fmt) fmt_fb32(v float32) { f.padString(strconv.Ftoa32(v, 'b', 0)) }
|
||||
|
||||
// fmt_c64 formats a complex64 according to its fmt_x argument.
|
||||
// TODO pass in a method rather than a byte when the compilers mature.
|
||||
func (f *fmt) fmt_c64(v complex64, fmt_x byte) {
|
||||
// fmt_c64 formats a complex64 according to the verb.
|
||||
func (f *fmt) fmt_c64(v complex64, verb int) {
|
||||
f.buf.WriteByte('(')
|
||||
r := real(v)
|
||||
f.preserveFlags = true
|
||||
for i := 0; ; i++ {
|
||||
switch fmt_x {
|
||||
switch verb {
|
||||
case 'e':
|
||||
f.fmt_e32(r)
|
||||
case 'E':
|
||||
@ -451,14 +369,13 @@ func (f *fmt) fmt_c64(v complex64, fmt_x byte) {
|
||||
f.buf.Write(irparenBytes)
|
||||
}
|
||||
|
||||
// fmt_c128 formats a complex128 according to its fmt_x argument.
|
||||
// TODO pass in a method rather than a byte when the compilers mature.
|
||||
func (f *fmt) fmt_c128(v complex128, fmt_x byte) {
|
||||
// fmt_c128 formats a complex128 according to the verb.
|
||||
func (f *fmt) fmt_c128(v complex128, verb int) {
|
||||
f.buf.WriteByte('(')
|
||||
r := real(v)
|
||||
f.preserveFlags = true
|
||||
for i := 0; ; i++ {
|
||||
switch fmt_x {
|
||||
switch verb {
|
||||
case 'e':
|
||||
f.fmt_e64(r)
|
||||
case 'E':
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,29 +34,6 @@ type ScanfMultiTest struct {
|
||||
err string
|
||||
}
|
||||
|
||||
type (
|
||||
renamedBool bool
|
||||
renamedInt int
|
||||
renamedInt8 int8
|
||||
renamedInt16 int16
|
||||
renamedInt32 int32
|
||||
renamedInt64 int64
|
||||
renamedUint uint
|
||||
renamedUint8 uint8
|
||||
renamedUint16 uint16
|
||||
renamedUint32 uint32
|
||||
renamedUint64 uint64
|
||||
renamedUintptr uintptr
|
||||
renamedString string
|
||||
renamedBytes []byte
|
||||
renamedFloat float
|
||||
renamedFloat32 float32
|
||||
renamedFloat64 float64
|
||||
renamedComplex complex
|
||||
renamedComplex64 complex64
|
||||
renamedComplex128 complex128
|
||||
)
|
||||
|
||||
var (
|
||||
boolVal bool
|
||||
intVal int
|
||||
@ -122,7 +99,7 @@ func (x *Xs) Scan(state ScanState, verb int) os.Error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !testing.MustCompile(string(verb) + "+").MatchString(tok) {
|
||||
if !testing.MustCompile("^" + string(verb) + "+$").MatchString(tok) {
|
||||
return os.ErrorString("syntax error for xs")
|
||||
}
|
||||
*x = Xs(tok)
|
||||
|
@ -26,21 +26,21 @@ type TF64 float64
|
||||
type TB bool
|
||||
type TS string
|
||||
|
||||
func (v TI) String() string { return Sprintf("I: %d", v) }
|
||||
func (v TI8) String() string { return Sprintf("I8: %d", v) }
|
||||
func (v TI16) String() string { return Sprintf("I16: %d", v) }
|
||||
func (v TI32) String() string { return Sprintf("I32: %d", v) }
|
||||
func (v TI64) String() string { return Sprintf("I64: %d", v) }
|
||||
func (v TU) String() string { return Sprintf("U: %d", v) }
|
||||
func (v TU8) String() string { return Sprintf("U8: %d", v) }
|
||||
func (v TU16) String() string { return Sprintf("U16: %d", v) }
|
||||
func (v TU32) String() string { return Sprintf("U32: %d", v) }
|
||||
func (v TU64) String() string { return Sprintf("U64: %d", v) }
|
||||
func (v TUI) String() string { return Sprintf("UI: %d", v) }
|
||||
func (v TF) String() string { return Sprintf("F: %f", v) }
|
||||
func (v TF32) String() string { return Sprintf("F32: %f", v) }
|
||||
func (v TF64) String() string { return Sprintf("F64: %f", v) }
|
||||
func (v TB) String() string { return Sprintf("B: %t", v) }
|
||||
func (v TI) String() string { return Sprintf("I: %d", int(v)) }
|
||||
func (v TI8) String() string { return Sprintf("I8: %d", int8(v)) }
|
||||
func (v TI16) String() string { return Sprintf("I16: %d", int16(v)) }
|
||||
func (v TI32) String() string { return Sprintf("I32: %d", int32(v)) }
|
||||
func (v TI64) String() string { return Sprintf("I64: %d", int64(v)) }
|
||||
func (v TU) String() string { return Sprintf("U: %d", uint(v)) }
|
||||
func (v TU8) String() string { return Sprintf("U8: %d", uint8(v)) }
|
||||
func (v TU16) String() string { return Sprintf("U16: %d", uint16(v)) }
|
||||
func (v TU32) String() string { return Sprintf("U32: %d", uint32(v)) }
|
||||
func (v TU64) String() string { return Sprintf("U64: %d", uint64(v)) }
|
||||
func (v TUI) String() string { return Sprintf("UI: %d", uintptr(v)) }
|
||||
func (v TF) String() string { return Sprintf("F: %f", float(v)) }
|
||||
func (v TF32) String() string { return Sprintf("F32: %f", float32(v)) }
|
||||
func (v TF64) String() string { return Sprintf("F64: %f", float64(v)) }
|
||||
func (v TB) String() string { return Sprintf("B: %t", bool(v)) }
|
||||
func (v TS) String() string { return Sprintf("S: %q", string(v)) }
|
||||
|
||||
func check(t *testing.T, got, want string) {
|
||||
|
@ -10,7 +10,7 @@ import "fmt"
|
||||
|
||||
type T int
|
||||
|
||||
func (t T) String() string { return fmt.Sprintf("T%d", t) }
|
||||
func (t T) String() string { return fmt.Sprintf("T%d", int(t)) }
|
||||
|
||||
const (
|
||||
A T = 1 << (1 << iota)
|
||||
|
Loading…
Reference in New Issue
Block a user