liveBook · Manning

Reflect.Type

As explained in Go in Practice, Second Edition

reflect.Type is a Go reflection interface that represents a type and provides operations for querying its properties and relationships.

When a Go program needs to inspect an unknown value at runtime, reflect.Type describes its specific type. It is distinct from reflect.Value, which represents the value, and reflect.Kind, which identifies a broad category such as struct, pointer, or string. section 13.1

A useful case is checking an interface chosen at runtime. Obtain the concrete type with reflect.ValueOf(concrete).Type(). For a target supplied as a pointer to an interface, reflect.TypeOf(target).Elem() yields the interface type; then call the concrete type’s Implements method. The target must have that pointer-to-interface form, or this unchecked approach can panic. section 13.1.2

Listing 13.5 Determining whether a type implements an interface
package main

import (
     "fmt"
     "io"
     "reflect"
)

type Name struct {                    #1
     First, Last string
}

func (n *Name) String() string {     
     return n.First + " " + n.Last
}

func main() {                        
     n := &Name{First: "Inigo", Last: "Montoya"}
     stringer := (*fmt.Stringer)(nil)                 #2
     implements(n, stringer)              #3
     writer := (*io.Writer)(nil)  #4
     implements(n, writer)   #5
}

func implements(concrete interface{}, target interface{}) bool {
     iface := reflect.TypeOf(target).Elem()   #6
     v := reflect.ValueOf(concrete)           #7
     t := v.Type()                            #7
     if t.Implements(iface) {   #8
            fmt.Printf("%T is a %s\n", concrete, iface.Name())
            return true
     }
     fmt.Printf("%T is not a %s\n", concrete, iface.Name())
     return false
}

The listing tests a pointer to Name against fmt.Stringer and io.Writer using reflect.Type and Implements. section 13.1.2

reflect.Type also helps inspect structs. Start with a reflect.Value, obtain its Type, and examine fields while walking nested values. A recursive walker can report each field’s type and kind, following struct fields until it reaches nonstruct kinds. section 13.1.3

     Value is type "main.Person" (struct)
            Field "Name" is type "*main.Name" (struct)
            Value is type "main.Name" (struct)
                   Field "Title" is type "string" (string)
                   Field "First" is type "string" (string)
                   Field "Last" is type "string" (string)
            Field "Address" is type "*main.Address" (struct)
            Value is type "main.Address" (struct)
                   Field "Street" is type "string" (string)
                   Field "Region" is type "string" (string)

The walker’s output makes the distinction between a pointer-typed field and the nested struct value visible. section 13.1.3

How Go in Practice, Second Edition covers it

How deep it goes
Works through TypeOf, Elem, Value.Type, and Implements, then applies type inspection in a recursive struct walker.
Examples
Tests a Name pointer against fmt.Stringer and io.Writer, and walks an integer, a simple struct, and nested structs.
What it assumes
Assumes familiarity with Go values, interfaces, pointers, and structs while introducing reflection’s value, type, and kind distinctions.
What you can do after
Apply it via Go’s reflect package to test interface implementation at runtime and inspect struct types and fields.
How it connects
Links reflect.Type with reflect.Value, reflect.Kind, interfaces, pointers, and structs.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go in Practice, Second Edition. The section links point to the parts of the book it draws on.