The verb %q
prints the contents of a string as it appears if you declared it as an interpreted string literal in your Go source code, i.e. with escape sequences and enclosed in double quotes "
.
The verb %#q
does the same, but as a raw string literal, with no escape sequences and enclosed in backquotes `
.
The fmt
package documentation reports this example:
Strings are formatted with %v and %s as-is, with %q as quoted strings, and %#q as backquoted strings.
placeholders := `foo "bar"`
fmt.Printf("%v %s %q %#q\n", placeholders, placeholders, placeholders, placeholders)
// Result: foo "bar" foo "bar" "foo \"bar\"" `foo "bar"`
Let's say you want to declare a string variable whose content is the character "
. How would you write that in your Go source? With an interpreted string literal, you would have to escape it, and with a raw string literal you would just enclose it in backquotes. Therefore:
This is mostly relevant when your string contains characters that should be escaped.
In other words:
func main() {
v := "\""
w := `"`
fmt.Printf("%q\n", v) // prints "\"", same as I just declared v
fmt.Printf("%#q\n", w) // prints `"`, same as I just declared w
}
As a side effect of this copy-paste use case, a practical application of either format verb is to inspect the run-time value of string variables for invisible characters, which you would have to type out somehow if you used it in Go source code.
There's one special case worth mentioning, which is also found in the fmt
package docs:
#
alternate format: [...] for %q, print a raw (backquoted) string if strconv.CanBackquote returns true; [...]
And jump to the docs of strconv.CanBackquote
:
CanBackquote reports whether the string s can be represented unchanged as a single-line backquoted string without control characters other than tab.
Notably, CanBackquote
returns false for strings that contain the backquote character itself or newline character \n
, as in the latter case the string can not be represented as a single-line. (See also How do you write multiline strings in Go?)
So in these cases the flag #
would have no effect and %#q
would print the same as %q
.
func main() {
v := "\n"
w := `
`
fmt.Printf("%q\n", v) // prints "\n", same as I just declared v
fmt.Printf("%#q\n", w) // prints "\n" too, because CanBackquote returns false
}