If you want go print type or golang print type of variable output while debugging, start with fmt and the %T verb. When you need richer metadata (golang get type as a reflect.Type, not only a string), use reflect.TypeOf and often .Kind(). Searches like golang print type of object, golang print object, or go print object usually mean the dynamic type inside an interface{} / any—Go has no separate “object” keyword, but interfaces carry a concrete value whose type %T shows. For printing whole structs, see print struct in Go; for struct definitions, see structs in Go.
Checked with Go 1.24 on 64-bit Linux (Fedora and Ubuntu family).
golang print type with %T and reflect.TypeOf
go print type of variable with %T
fmt.Printf with %T is the lightest print type golang option: no reflect import, and the output matches Go source type syntax.
golang get type with reflect
reflect.TypeOf(v) returns a reflect.Type. Call .String() when you need a name string; call .Kind() to distinguish broad categories (slice, ptr, struct, func, …) without string parsing.
package main
import (
"fmt"
"reflect"
)
func main() {
var i any = 42
fmt.Printf("dynamic type: %T\n", i)
fmt.Println("reflect.TypeOf:", reflect.TypeOf(i))
fmt.Println("Kind:", reflect.TypeOf(i).Kind())
x := 3
fmt.Printf("value type: %T pointer type: %T\n", x, &x)
var j any = []int{1, 2}
fmt.Printf("slice type=%T kind=%v\n", j, reflect.TypeOf(j).Kind())
}You should see int for the any holding 42, *int for the address of x, and []int with kind=slice for j.
Pointers, any, and nil
%T on a concrete pointer prints the pointer type (for example *main.Person). For an any holding nil, %T prints <nil> and reflect.TypeOf returns a nil reflect.Type because there is no dynamic type to describe. A typed nil pointer still has a type (*int, *bytes.Buffer, …).
Type switches when you branch instead of log
A type switch chooses behavior per type; it is not a magic golang print type printer, but the default branch can fall back to %T or reflect.TypeOf(v).String() so you never print unknown for cases you forgot to list (the pitfall in older tutorials). For control-flow style switches without reflection metadata, see switch in Go.
package main
import (
"fmt"
"reflect"
)
func describe(v any) string {
switch v.(type) {
case int, int8, int16, int32, int64:
return "signed integer"
case string:
return "string"
case bool:
return "bool"
default:
return reflect.TypeOf(v).String()
}
}
func main() {
for _, v := range []any{"a", 6, true, []int{1}} {
fmt.Println(describe(v))
}
}You should see string, signed integer, bool, and []int.
Summary
Golang print type and go print type of variable tasks are usually fmt.Printf("%T", v). Golang get type detail lives in reflect.TypeOf plus Kind and optional field introspection. Golang print type of object and print object golang phrasing maps to any dynamic types: %T shows the concrete type stored in the interface box, while reflect.TypeOf returns nil when that box is empty. Combine type switch branches for hand-written categories with a default that defers to reflect so you never silently label real types as unknown.
References
- Package fmt
- Package reflect
- Type assertions (Go spec)
- How to find the type of an object in Go? (Stack Overflow)

