Skip to content

Instantly share code, notes, and snippets.

Created Apr 20, 2016
What would you like to do?
A detailed example of reflection in Go, interrogating and modifying field values in a struct
package main
import (
// A detailed example of examining a struct value in Go via reflection,
// and changing field values (if possible).
// See <>
// for accompanying article.
type Name string
type Person struct {
FirstName Name
LastName Name
Age int
func reflectOn(s interface{}) {
// Get the type and value of the argument we were passed.
ptyp := reflect.TypeOf(s)
pval := reflect.ValueOf(s)
// We can't do much with the Value (it's opaque), but we need it in order
// to fetch individual fields from the struct later.
var typ reflect.Type
var val reflect.Value
// If we were passed a pointer, dereference to get the type and value
// pointed at.
if ptyp.Kind() == reflect.Ptr {
fmt.Printf("Argument is a pointer, dereferencing.\n")
typ = ptyp.Elem()
val = pval.Elem()
} else {
fmt.Printf("Argument is %s.%s, a %s.\n", ptyp.PkgPath(), ptyp.Name(),
typ = ptyp
val = pval
// Make sure we now have a struct
if typ.Kind() != reflect.Struct {
fmt.Printf("Not a struct.\n")
// Can we set values?
if val.CanSet() {
fmt.Printf("We can set values.\n")
} else {
fmt.Printf("We cannot set values.\n")
// The number of fields in the struct is determined by the type of struct
// it is. Loop through them.
for i := 0; i < typ.NumField(); i++ {
// Get the type of the field from the type of the struct. For a struct,
// you always get a StructField.
sfld := typ.Field(i)
// Get the type of the StructField, which is the type actually stored
// in that field of the struct.
tfld := sfld.Type
// Get the Kind of that type, which will be the underlying base type
// used to define the type in question.
kind := tfld.Kind()
// Get the value of the field from the value of the struct.
vfld := val.Field(i)
// Dump out what we've found
fmt.Printf("struct field %d: name %s type %s kind %s value %v\n", i,
sfld.Name, tfld, kind, vfld)
// Is that field some kind of string, and is the value one we can set?
if kind == reflect.String && vfld.CanSet() {
fmt.Printf("Overwriting field %s\n", sfld.Name)
// Assign to it
func main() {
t := Person{"John", "Smith", 23}
fmt.Printf("First, passing the actual structure:\n\n")
fmt.Printf("After reflection:\n%s %s, %d years old\n",
t.FirstName, t.LastName, t.Age)
fmt.Printf("\nNow, passing a pointer to the structure:\n\n")
fmt.Printf("After reflection:\n%s %s, %d years old\n",
t.FirstName, t.LastName, t.Age)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment