When a function accepts arbitrary Go values, a type switch can select behavior for each concrete type. That becomes repetitive when several types need the same treatment. A defined type such as `type MyInt int64` also needs its own type-switch case. `reflect.Kind` identifies a value’s broader category instead: `MyInt` has its own type but the kind `reflect.Int64`. Go’s `reflect` package also distinguishes the value, represented by `reflect.Value`, from its type, available through `reflect.Type`. section 13.1 section 13.1.1
Sum values by kind
This program accepts mixed values, converts the supported kinds to `float64`, and prints `43.200000`: ```go package main import ( "fmt" "reflect" "strconv" ) type MyInt int64 func sum(values ...interface{}) float64 { var total float64 for _, value := range values { reflected := reflect.ValueOf(value) switch reflected.Kind() { case reflect.Int, reflect.Int64: total += float64(reflected.Int()) case reflect.Uint8: total += float64(reflected.Uint()) case reflect.String: number, err := strconv.ParseFloat(reflected.String(), 64) if err != nil { panic(err) } total += number default: fmt.Printf("Unsupported type %T. Ignoring.\n", value) } } return total } func main() { fmt.Printf("Result: %f\n", sum(uint8(2), 37, "3.2", MyInt(1))) } ``` `reflect.ValueOf` obtains a reflection value; `Kind()` supplies the switch condition. The `reflect.Int64` case accepts `MyInt` without naming that type. Choose a type switch when behavior depends on specific types; a kind switch is less common, but useful when the same operation applies across underlying categories. section 13.1.1
Kinds also guide runtime inspection. A struct walker can inspect a value’s type and kind, then recurse through struct fields until it reaches nonstruct kinds. Pointer values need attention during that walk; `reflect.Indirect(reflect.ValueOf(u))` obtains the value being examined. section 13.1.3
Listing 13.7 Recursively examining a value
func main() {
fmt.Println("Walking a simple integer")
var one MyInt = 1 #1
walk(one, 0) #1
fmt.Println("Walking a simple struct")
two := struct{ Name string }{"foo"} #2
walk(two, 0) #2
fmt.Println("Walking a struct with struct fields") #2
p := &Person{ #3
Name: &Name{"Count", "Tyrone", "Rugen"
},
Address: &Address{"Humperdink Castle",
"Florian"},
}
walk(p, 0)
}
type MyInt int
type Person struct {
Name *Name
Address *Address
}
type Name struct {
Title, First, Last string
}
type Address struct {
Street, Region string
}
func walk(u interface{}, depth int) { #4
val := reflect.Indirect(reflect.ValueOf(u)) #5
t := val.Type() #6
tabs := strings.Repeat("\t", depth+1) #7
fmt.Printf("%sValue is type %q (%s)\n", tabs, t, val.Kind())
if val.Kind() == reflect.Struct { #8
for i := 0; i < t.NumField(); i++ {
field := t.Field(i) #9
fieldVal := reflect.Indirect
(val.Field(i))
tabs := strings.Repeat("\t", depth+2)
fmt.Printf("%sField %q is type %q (%s)\n",
tabs, field.Name, field.Type, fieldVal.Kind())
if fieldVal.Kind() ==
reflect.Struct { #10
walk(fieldVal.Interface(), depth+1) #10
} #10
}
}
}
See the recursive value walker for a larger example combining types, values, kinds, and pointer indirection. section 13.1.3
