Go String Formatting Verbs

%s, %d, %v, %+v, %#v Explained

Use `%s` for strings, `%d` for integers, and `%v` for the default representation of any value.

Use %s for strings, %d for integers, and %v for the default representation of any value. Choose %+v to include struct field names and #v for a Go-syntax literal representation that includes type information.

The fmt package handles these verbs consistently, but the output varies significantly based on the data type and the specific verb used. %s expects a string or byte slice; if you pass a non-string, it will panic. %d is strictly for integers. %v is the most flexible, printing the value in a default format (e.g., 123 for an int, hello for a string, or field:value for a struct without names).

When debugging structs, %+v is essential because it prefixes values with field names, making it easy to identify which field holds which data. #v is unique because it outputs a Go syntax representation of the value, which is incredibly useful for verifying data structures or generating code snippets, as it includes type information and quotes for strings.

Here are practical examples showing the differences in output:

package main

import (
	"fmt"
)

type User struct {
	ID   int
	Name string
	Role string
}

func main() {
	u := User{ID: 42, Name: "Alice", Role: "admin"}

	// %s: Only works for strings or []byte
	fmt.Printf("Name: %s\n", u.Name) 

	// %d: Only works for integers
	fmt.Printf("ID: %d\n", u.ID)

	// %v: Default format (no field names for structs)
	fmt.Printf("Default: %v\n", u) 
	// Output: {42 Alice admin}

	// %+v: Includes field names (great for debugging)
	fmt.Printf("With Names: %+v\n", u) 
	// Output: {ID:42 Name:Alice Role:admin}

	// %#v: Go syntax representation (includes type and quotes)
	fmt.Printf("Go Syntax: %#v\n", u) 
	// Output: main.User{ID:42, Name:"Alice", Role:"admin"}
}

For command-line tools, %v is usually sufficient for quick logs, but %+v is preferred when you need to trace specific struct fields during development. Use #v when you need to copy-paste the output back into Go code or when you need to see the exact type of a variable in a generic context. Avoid %s for non-string types unless you explicitly convert them first, as it will cause a runtime panic.