Golang print struct: fmt verbs, pretty JSON, and type names

Print struct golang and go print struct with fmt.Printf verbs (%v %+v %#v), golang pretty print struct via encoding/json, golang print type of variable with %T and reflect.TypeOf, fmt.Stringer, and optional go-spew.

Published

Updated

Read time 3 min read

Reviewed byDeepak Prasad

Golang print struct: fmt verbs, pretty JSON, and type names

If you want to print struct golang values while debugging, you usually reach for fmt.Printf first, then switch to JSON when you need a golang pretty print struct layout for APIs or logs. The same ideas apply when people say go print struct or golang print object—they mean “show me the fields.” This page covers golang printf struct verbs (%v, %+v, %#v), pretty print struct golang with encoding/json, golang print type of variable with %T and reflect.TypeOf, the fmt.Stringer hook, and optionally go-spew for deep dumps. For struct basics, see structs in Go; for JSON tags and decoding, see parse JSON in Go.

Checked with Go 1.24 on 64-bit Linux (Fedora and Ubuntu family).


golang print struct with fmt and encoding/json

golang printf struct: %v, %+v, %#v, and %T

The fmt package is the fastest way to print struct golang values to the terminal:

  • %v — default value format (compact struct without field names in this mode).
  • %+v — adds field names for structs (what many people mean by pretty print struct golang in plain text).
  • %#v — Go-syntax representation, useful when you want something you could paste back into code.
  • %T — dynamic type of the operand; answers golang print type of variable for concrete values.
go
package main

import (
	"encoding/json"
	"fmt"
	"reflect"
)

type Person struct {
	ID    int
	Name  string
	Phone string
}

func main() {
	p := Person{1, "Anna", "+125639842"}
	fmt.Printf("%%v:  %v\n", p)
	fmt.Printf("%%+v: %+v\n", p)
	fmt.Printf("%%#v: %#v\n", p)
	fmt.Printf("%%T:  %T\n", p)
	fmt.Println(reflect.TypeOf(p))

	b, err := json.MarshalIndent(p, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Printf("json:\n%s\n", string(b))
}
Output

You should see {1 Anna ...} for %v, field names for %+v, a main.Person{...} literal for %#v, main.Person for %T, the same type from reflect.TypeOf, and indented JSON at the end.

golang pretty print struct as JSON

json.MarshalIndent is the usual golang pretty print struct choice when humans read the output. Only exported fields (names starting with an uppercase letter) are marshaled; unexported fields are omitted silently unless you use custom MarshalJSON logic.

golang print type of variable and interfaces

For a concrete variable p, %T and reflect.TypeOf(p) agree on the static type. For an interface{} / any holding different concrete types, %T prints the dynamic type. Combine that with a type switch when you need different formatting per case.

fmt.Stringer instead of a custom ToString

The idiomatic hook for go print struct output used by fmt.Print and friends is String() string, not a Java-style toString name:

go
package main

import "fmt"

type Person struct {
	ID   int
	Name string
}

func (p Person) String() string {
	return fmt.Sprintf("Person(%s)", p.Name)
}

func main() {
	fmt.Println(Person{1, "Anna"})
}
Output

You should see a single line starting with Person(.

Optional: deep dumps with go-spew

For interactive debugging, spew.Dump walks nested values and annotates lengths and pointers. It lives outside the standard library, so add a dependency and run locally:

bash
go get github.com/davecgh/go-spew@v1.1.1
go
package main

import "github.com/davecgh/go-spew/spew"

type Person struct {
	ID   int
	Name string
}

func main() {
	spew.Dump(Person{1, "Anna"})
}

Expect labeled fields, string lengths, and pointer addresses in the style of spew’s formatter.


Summary

Golang print struct workflows usually start with golang printf struct verbs: %+v for field names, %#v for Go syntax, %T or reflect.TypeOf for golang print type of variable. Pretty print struct golang output for humans often means json.MarshalIndent, remembering JSON only sees exported fields. For stable one-line logs, implement fmt.Stringer. Go print object phrasing maps to the same tools once you know the concrete type behind an interface. Third-party go-spew remains handy for dense debugging dumps when plain fmt is not enough.


References


Frequently Asked Questions

1. How do I golang print struct field names?

Use fmt.Printf with %+v so each field prints with its name; plain %v omits names for structs. %#v prints a Go-syntax literal including package and type.

2. How do I golang pretty print struct as JSON?

Call json.MarshalIndent with your value, empty prefix, and a tab or two spaces for indent. Only exported struct fields appear; unexported fields are skipped.

3. How do I golang print type of variable?

Use fmt.Printf("%T", v) for a short type string in the same notation you would write in code, or reflect.TypeOf(v) when you need a reflect.Type for inspection.

4. Is golang print object different from printing a struct?

In Go there is no separate object type; if you hold a struct inside an interface{}, printing still uses the dynamic value—use %v, %+v, %#v, or a type switch depending on what you need.

5. When should I use go-spew instead of fmt?

spew.Dump gives deep, labeled output for pointers, slices, and nested values during debugging. It is a third-party module; for production logs prefer fmt, slog, or structured JSON.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise …