Home > OS >  What's the difference between the `%q` and the `%#q` string formatters?
What's the difference between the `%q` and the `%#q` string formatters?

Time:07-08

I don't get the meaning of # when used with q.

fmt.Printf("%q", "\"")
fmt.Println()
fmt.Printf("%#q", "\"")

prints

"\""
`"`

but

fmt.Printf("%q", "\n")
fmt.Println()
fmt.Printf("%#q", "\n")

prints

"\n"
"\n"

There are more examples at https://cs.opensource.google/go/go/ /master:src/fmt/fmt_test.go.

    {"%q", "", `""`},
    {"%#q", "", "``"},
    {"%q", "\"", `"\""`},
    {"%#q", "\"", "`\"`"},
    {"%q", "`", `"`   "`"   `"`},
    {"%#q", "`", `"`   "`"   `"`},
    {"%q", "\n", `"\n"`},
    {"%#q", "\n", `"\n"`},
    {"%q", `\n`, `"\\n"`},
    {"%#q", `\n`, "`\\n`"},
    {"%q", "abc", `"abc"`},
    {"%#q", "abc", "`abc`"},

CodePudding user response:

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:

  • The output of %q is "\"" that you can copy-paste in Go code as an interpreted string literal.

  • The output of %#q is " that you can copy-paste in Go code as a raw string literal.

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.

CodePudding user response:

%q prints the value as a quoted string.
%#q prints the value as a quoted string as Go syntax.

In general, adding # between % and the type causes output to be in Go code - syntactically correct that you could copy-paste into your program.

This example illustrates the effect of the #:

s := []string{"foo", "bar", "baz"}
fmt.Printf("%v\n", s)
fmt.Printf("%#v\n", s)
fmt.Printf("%q\n", s)
fmt.Printf("%#q\n", s)

Produces:

[foo bar baz]
[]string{"foo", "bar", "baz"}
["foo" "bar" "baz"]
[`foo` `bar` `baz`]

See live demo.

  • Related