dont use sprintf to convert types to string
https://philpearl.github.io/post/bad_go_sprintf/
fmt.Sprintf("%d", i) vs strconv.FormatInt(int64(i), 10)
- fmt.Sprintf needs to parse its first argument to understand what to do. But in these examples the programmer knows there’s just a single very simple task required: convert this number to a string, or this boolean to a string. Why not just do that directly?
- fmt.Sprintf needs to marshal its variable arguments into a slice of interface{}. The compiler has improved a lot here, but this could cause unnecessary allocations. There are simpler functions for the same task that don’t need variable arguments or interface arguments.
- But this isn’t all bashing fmt.Sprintf. fmt.Sprintf is great. But when you use it, use it. Build the whole string. Don’t build tiny pieces and concatenate them. Concatenating strings causes allocations. Allocations are the bane of the life of anyone trying to squeeze performance out of Go.
func BenchmarkSprintfNumber(b *testing.B) {
b.ReportAllocs()
vals := make([]string, b.N)
for i := 0; i < b.N; i++ {
vals[i] = fmt.Sprintf("%d", i)
}
}
func BenchmarkSprintfStrconvNumber(b *testing.B) {
b.ReportAllocs()
vals := make([]string, b.N)
for i := 0; i < b.N; i++ {
vals[i] = strconv.FormatInt(int64(i), 10)
}
}
name time/op
SprintfNumber-8 133ns ± 2%
SprintfStrconvNumber-8 45.1ns ± 2%
name alloc/op
SprintfNumber-8 32.0B ± 0%
SprintfStrconvNumber-8 23.0B ± 0%
name allocs/op
SprintfNumber-8 2.00 ± 0%
SprintfStrconvNumber-8 0.00
Padding integers
Escape sequences
ASCII Control codes:
\a alert or bell
\b backspace
\f form feed
\n newline
\r carriage return
\t tab
\v vertical tab
\' single qoute
\" double qoute
\\ backslash
` ` raw string literal (contents taken literally)
Bytes:
\xhh byte by hexadecimal
\ooo byte by octal digits
verbs
go doc fmt
The format 'verbs' are derived from C's but are simpler.
General:
%v the value in a default format
when printing structs, the plus flag (%+v) adds field names
%#v a Go-syntax representation of the value
%T a Go-syntax representation of the type of the value
%% a literal percent sign; consumes no value
Width:
Width is specified by an optional decimal number immediately preceding the verb.
If absent, the width is whatever is necessary to represent the value. Precision
is specified after the (optional) width by a period followed by a decimal
number. If no period is present, a default precision is used. A period with no
following number specifies a precision of zero. Examples:
%f default width, default precision
%9f width 9, default precision
%.2f default width, precision 2
%9.2f width 9, precision 2
%9.f width 9, precision 0
Boolean:
%t the word true or false
Integer:
%b base 2
%c the character represented by the corresponding Unicode code point
int
%d base 10
%o base 8
%O base 8 with 0o prefix
%q a single-quoted character literal safely escaped with Go syntax
x.
%x base 16, with lower-case letters for a-f
%X base 16, with upper-case letters for A-F
%U Unicode format: U+1234; same as "U+%04X"
Floating-point and complex constituents:
%b decimalless scientific notation with exponent a power of two,
in the manner of strconv.FormatFloat with the 'b' format,
e.g. -123456p-78
%e scientific notation, e.g. -1.234456e+78
%E scientific notation, e.g. -1.234456E+78
%f decimal point but no exponent, e.g. 123.456
%F synonym for %f
%g %e for large exponents, %f otherwise. Precision is discussed b
elow.
%G %E for large exponents, %F otherwise
%x hexadecimal notation (with decimal power of two exponent), e.g
. -0x1.23abcp+20
%X upper-case hexadecimal notation, e.g. -0X1.23ABCP+20
String and slice of bytes (treated equivalently with these verbs):
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Go syntax
%x base 16, lower-case, two characters per byte
%X base 16, upper-case, two characters per byte
Slice:
%p address of 0th element in base 16 notation, with leading 0x
Pointer:
%p base 16 notation, with leading 0x
The %b, %d, %o, %x and %X verbs also work with pointers,
formatting the value exactly as if it were an integer.
The default format for %v is:
bool: %t
int, int8 etc.: %d
uint, uint8 etc.: %d, %#x if printed with %#v
float32, complex64, etc: %g
string: %s
chan: %p
pointer: %p