← 结构体反射 | 修改值 →

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+ 优先使用泛型