Type 和 Value - 反射核心
reflect.Type 和 reflect.Value 是 Go 反射的两大核心概念。Type 表示类型信息,Value 表示值信息。深入理解它们是掌握反射的关键。
📌 核心概念
🏷️
reflect.Type
类型信息
TypeOf()
⚖️
reflect.Value
值信息
ValueOf()
📊
Kind
类型类别
Kind()
🔄
转换
Type/Value 互转
Interface()
reflect.Type 详解
📖 Type 类型信息
package main
import (
"fmt"
"reflect"
)
func inspectType(v interface{}) {
t := reflect.TypeOf(v)
fmt.Printf("Type: %v\n", t)
fmt.Printf("Name: %v\n", t.Name())
fmt.Printf("Kind: %v\n", t.Kind())
fmt.Printf("String: %v\n", t.String())
// 复杂类型信息
switch t.Kind() {
case reflect.Struct:
fmt.Printf("NumField: %d\n", t.NumField())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fmt.Printf(" Field %d: %s (%v)\n",
i, field.Name, field.Type)
}
case reflect.Slice, reflect.Array:
fmt.Printf("Elem: %v\n", t.Elem())
fmt.Printf("Len: %d\n", t.Len())
case reflect.Map:
fmt.Printf("Key: %v, Elem: %v\n",
t.Key(), t.Elem())
case reflect.Ptr:
fmt.Printf("Elem: %v\n", t.Elem())
case reflect.Func:
fmt.Printf("NumIn: %d, NumOut: %d\n",
t.NumIn(), t.NumOut())
}
}
type Person struct {
Name string
Age int
}
func main() {
inspectType(42)
inspectType([]int{1, 2, 3})
inspectType(make(map[string]int))
inspectType(Person{})
}
💡 Type 要点
- TypeOf: 获取 reflect.Type
- Kind vs Type: Kind 是类别,Type 是具体类型
- Name: 类型名称(非基本类型才有)
- 只读: Type 信息是只读的
reflect.Value 详解
📖 Value 值信息
package main
import (
"fmt"
"reflect"
)
func inspectValue(v interface{}) {
val := reflect.ValueOf(v)
fmt.Printf("Kind: %v\n", val.Kind())
fmt.Printf("Type: %v\n", val.Type())
fmt.Printf("CanSet: %v\n", val.CanSet())
fmt.Printf("CanAddr: %v\n", val.CanAddr())
// 获取值
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int64:
fmt.Printf("Int: %d\n", val.Int())
case reflect.Uint, reflect.Uint64:
fmt.Printf("Uint: %d\n", val.Uint())
case reflect.Float64:
fmt.Printf("Float: %f\n", val.Float())
case reflect.String:
fmt.Printf("String: %s\n", val.String())
case reflect.Bool:
fmt.Printf("Bool: %v\n", val.Bool())
case reflect.Slice:
fmt.Printf("Len: %d, Cap: %d\n",
val.Len(), val.Cap())
case reflect.Struct:
fmt.Printf("NumField: %d\n", val.NumField())
case reflect.Ptr:
fmt.Printf("IsNil: %v\n", val.IsNil())
if !val.IsNil() {
fmt.Printf("Elem: %v\n", val.Elem())
}
}
// 获取底层值
fmt.Printf("Interface: %v\n", val.Interface())
}
func main() {
inspectValue(42)
inspectValue("hello")
inspectValue([]int{1, 2, 3})
ptr := new(int)
*ptr = 100
inspectValue(ptr)
}
Type 和 Value 转换
📝 Type/Value 互转
package main
import (
"fmt"
"reflect"
)
func main() {
original := 42
// interface{} → Type
t := reflect.TypeOf(original)
fmt.Printf("Type: %v\n", t)
// interface{} → Value
v := reflect.ValueOf(original)
fmt.Printf("Value: %v\n", v)
// Value → Type
t2 := v.Type()
fmt.Printf("From Value Type: %v\n", t2)
// Value → interface{}
iface := v.Interface()
fmt.Printf("Interface: %v (type: %T)\n", iface, iface)
// Type → 创建新 Value
newVal := reflect.New(t)
fmt.Printf("New Value: %v\n", newVal)
// 完整循环
// original → Value → Interface → Type
v2 := reflect.ValueOf(original)
iface2 := v2.Interface()
t3 := reflect.TypeOf(iface2)
fmt.Printf("Round trip: %v\n", t3)
}
Kind 类型类别
📖 Kind 与 Type 区别
package main
import (
"fmt"
"reflect"
)
type MyInt int
type MyString string
func main() {
var a int = 42
var b MyInt = 100
var c string = "hello"
var d MyString = "world"
// Kind: 底层类别
fmt.Printf("int Kind: %v\n", reflect.TypeOf(a).Kind())
fmt.Printf("MyInt Kind: %v\n", reflect.TypeOf(b).Kind())
// Type: 具体类型
fmt.Printf("int Type: %v\n", reflect.TypeOf(a))
fmt.Printf("MyInt Type: %v\n", reflect.TypeOf(b))
// Name: 类型名称
fmt.Printf("int Name: %v\n", reflect.TypeOf(a).Name())
fmt.Printf("MyInt Name: %v\n", reflect.TypeOf(b).Name())
// Kind 相同但 Type 不同
fmt.Printf("Same Kind: %v\n",
reflect.TypeOf(a).Kind() == reflect.TypeOf(b).Kind())
fmt.Printf("Same Type: %v\n",
reflect.TypeOf(a) == reflect.TypeOf(b))
}
实用模式
1. 通用类型检查
📝 类型检查函数
func checkType(v interface{}) string {
t := reflect.TypeOf(v)
switch t.Kind() {
case reflect.Int, reflect.Int8, reflect.Int64:
return "integer"
case reflect.Float32, reflect.Float64:
return "float"
case reflect.String:
return "string"
case reflect.Bool:
return "boolean"
case reflect.Slice:
return fmt.Sprintf("slice of %s", t.Elem().Kind())
case reflect.Map:
return fmt.Sprintf("map[%s]%s",
t.Key().Kind(), t.Elem().Kind())
default:
return t.Kind().String()
}
}
2. 动态调用
📝 反射调用函数
func add(a, b int) int {
return a + b
}
func callFunction() {
// 获取函数 Value
fn := reflect.ValueOf(add)
// 准备参数
args := []reflect.Value{
reflect.ValueOf(10),
reflect.ValueOf(20),
}
// 调用函数
results := fn.Call(args)
// 获取返回值
result := results[0].Int()
fmt.Println(result) // 30
}
最佳实践
✅ Type 和 Value 使用建议
- Kind 检查: 先检查 Kind 再操作 Value
- CanSet: 修改前检查 CanSet
- 缓存 Type: 避免重复获取 Type 信息
- 优先泛型: Go 1.18+ 优先使用泛型