Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Go reflect 包详解

概述

reflect 包实现了运行时反射,允许程序通过任意类型的值来检查其类型和值。它提供了强大的动态类型检查和操作能力。

重要提示:反射虽然强大,但应该谨慎使用。过度使用反射会导致代码难以理解和维护,性能也会下降。

反射三定律

  1. Reflection goes from interface value to reflection object(反射从接口值到反射对象)
  2. Reflection goes from reflection object to interface value(反射从反射对象到接口值)
  3. To modify a reflection object, the value must be settable(要修改反射对象,值必须是可设置的)

详细信息:The Laws of Reflection

包导入

import "reflect"

基本使用

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x float64 = 3.4
    
    // 获取类型信息
    t := reflect.TypeOf(x)
    fmt.Println("type:", t.Name())
    
    // 获取值信息
    v := reflect.ValueOf(x)
    fmt.Println("kind:", v.Kind())
    fmt.Println("value:", v.Float())
}

运行结果

type: float64
kind: float64
value: 3.4

常量

Ptr

const Ptr = ChanDir

说明PtrChanDir 的旧名称,已弃用,仅为兼容保留。

使用示例

// 不推荐使用,直接使用 ChanDir
dir := reflect.ChanDir(1) // 使用 ChanDir 而不是 Ptr

类型详解

ChanDir

ChanDir 表示通道的方向。

type ChanDir int

常量值

const (
    SendDir ChanDir = 1 << iota // 发送通道
    RecvDir                     // 接收通道
    BothDir = SendDir | RecvDir // 双向通道
)

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var sendChan chan<- int
    var recvChan <-chan int
    var bothChan chan int
    
    fmt.Println("sendChan dir:", reflect.TypeOf(sendChan).ChanDir())
    fmt.Println("recvChan dir:", reflect.TypeOf(recvChan).ChanDir())
    fmt.Println("bothChan dir:", reflect.TypeOf(bothChan).ChanDir())
}

运行结果

sendChan dir: 1
recvChan dir: 2
bothChan dir: 3

Kind

Kind 表示类型的种类。

type Kind uint

25 种类型种类

const (
    Invalid Kind = iota
    Bool
    Int
    Int8
    Int16
    Int32
    Int64
    Uint
    Uint8
    Uint16
    Uint32
    Uint64
    Uintptr
    Float32
    Float64
    Complex64
    Complex128
    Array
    Chan
    Func
    Interface
    Map
    Ptr
    Slice
    String
    Struct
    UnsafePointer
)

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    types := []interface{}{
        true,           // Bool
        int(42),        // Int
        float64(3.14),  // Float64
        []int{1, 2, 3}, // Slice
        map[string]int{"a": 1}, // Map
        struct{ Name string }{"test"}, // Struct
    }
    
    for _, v := range types {
        fmt.Printf("%T -> %s\n", v, reflect.TypeOf(v).Kind())
    }
}

运行结果

bool -> Bool
int -> Int
float64 -> Float64
[]int -> Slice
map[string]int -> Map
struct { Name string } -> Struct

MapIter

MapIter 表示 map 迭代器,与 Value.MapRange 方法一起使用。

type MapIter struct {
    // 未导出字段
}

方法

  • func (it *MapIter) Key() Value - 返回当前迭代位置的键
  • func (it *MapIter) Next() bool - 前进到下一个位置
  • func (it *MapIter) Value() Value - 返回当前迭代位置的值

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    m := map[string]int{
        "a": 1,
        "b": 2,
        "c": 3,
    }
    
    v := reflect.ValueOf(m)
    iter := v.MapRange()
    
    for iter.Next() {
        key := iter.Key()
        value := iter.Value()
        fmt.Printf("%s: %d\n", key.String(), value.Int())
    }
}

运行结果

a: 1
b: 2
c: 3

Method

Method 表示结构体或接口的方法。

type Method struct {
    Name    string      // 方法名
    PkgPath string      // 包路径(未导出方法)
    Type    Type        // 方法类型
    Func    Value       // 方法值
    Index   int         // 方法索引
    Tag     StructTag   // 方法标签
}

使用示例

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name string
}

func (p Person) SayHello() {
    fmt.Println("Hello from", p.Name)
}

func main() {
    var p Person
    t := reflect.TypeOf(p)
    
    for i := 0; i < t.NumMethod(); i++ {
        method := t.Method(i)
        fmt.Printf("Method %d: %s\n", i, method.Name)
    }
}

运行结果

Method 0: SayHello

SelectCase

SelectCase 表示 select 语句中的一个案例。

type SelectCase struct {
    Dir  SelectDir // 通道方向
    Chan Value     // 通道
    Send Value     // 要发送的值(仅用于发送)
}

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    ch1 := make(chan int, 1)
    ch2 := make(chan string, 1)
    
    cases := []reflect.SelectCase{
        {Dir: reflect.SelectSend, Chan: reflect.ValueOf(ch1), Send: reflect.ValueOf(42)},
        {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch2)},
    }
    
    chosen, recv, ok := reflect.Select(cases)
    fmt.Printf("chosen: %d, recv: %v, ok: %v\n", chosen, recv, ok)
}

SelectDir

SelectDir 表示 select 案例的方向。

type SelectDir int

常量值

const (
    SelectDefault SelectDir = iota // 默认案例
    SelectSend                     // 发送
    SelectRecv                     // 接收
)

SliceHeader

已弃用:使用 unsafe 包中的等效结构。

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

StringHeader

已弃用:使用 unsafe 包中的等效结构。

type StringHeader struct {
    Data uintptr
    Len  int
}

StructField

StructField 表示结构体的单个字段。

type StructField struct {
    Name      string      // 字段名
    PkgPath   string      // 包路径(未导出字段)
    Type      Type        // 字段类型
    Tag       StructTag   // 字段标签
    Offset    uintptr     // 字段偏移量
    Index     []int       // 字段索引(用于嵌套字段)
    Anonymous bool        // 是否为匿名字段
    Align     int         // 字段对齐
    Embedded  bool        // 是否为嵌入字段
}

使用示例

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    t := reflect.TypeOf(Person{})
    
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        fmt.Printf("Field %d: %s (type: %s, tag: %s)\n", 
            i, field.Name, field.Type, field.Tag)
    }
}

运行结果

Field 0: Name (type: string, tag: json:"name")
Field 1: Age (type: int, tag: json:"age")

StructTag

StructTag 表示结构体字段的标签。

type StructTag string

方法

  • func (tag StructTag) Get(key string) string - 获取标签值
  • func (tag StructTag) Lookup(key string) (string, bool) - 查找标签值

使用示例

package main

import (
    "fmt"
    "reflect"
)

type User struct {
    ID    int    `json:"id" db:"user_id"`
    Name  string `json:"name" db:"user_name"`
    Email string `json:"email,omitempty" db:"email"`
}

func main() {
    t := reflect.TypeOf(User{})
    
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        jsonTag, _ := field.Tag.Lookup("json")
        dbTag, _ := field.Tag.Lookup("db")
        fmt.Printf("%s: json=%s, db=%s\n", field.Name, jsonTag, dbTag)
    }
}

运行结果

ID: json=id, db=user_id
Name: json=name, db=user_name
Email: json=email,omitempty, db=email

Type

Type 表示 Go 类型的静态信息。

type Type interface {
    // 基本方法
    Align() int
    FieldAlign() int
    Method(int) Method
    MethodByName(string) (Method, bool)
    NumMethod() int
    
    // 类型信息
    Name() string
    PkgPath() string
    Size() uintptr
    String() string
    Kind() Kind
    
    // 类型操作
    Implements(u Type) bool
    AssignableTo(u Type) bool
    ConvertibleTo(u Type) bool
    Comparable() bool
    
    // 复合类型
    Elem() Type
    Key() Type
    NumField() int
    Field(i int) StructField
    FieldByName(name string) (StructField, bool)
    FieldByIndex(index []int) StructField
    FieldByNameFunc(match func(string) bool) (StructField, bool)
    
    // 通道
    ChanDir() ChanDir
    IsVariadic() bool
    
    // 方法构造
    Constructor() Func
}

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x int
    t := reflect.TypeOf(x)
    
    fmt.Println("Name:", t.Name())
    fmt.Println("Kind:", t.Kind())
    fmt.Println("Size:", t.Size())
    fmt.Println("String:", t.String())
}

运行结果

Name: int
Kind: int
Size: 8
String: int

Value

Value 表示 Go 值的运行时表示。

type Value struct {
    // 未导出字段
}

主要方法(60+ 个)

类型检查

  • func (v Value) IsValid() bool - 值是否有效
  • func (v Value) IsZero() bool - 值是否为零值
  • func (v Value) IsNil() bool - 值是否为 nil
  • func (v Value) CanAddr() bool - 值是否可寻址
  • func (v Value) CanSet() bool - 值是否可设置
  • func (v Value) Kind() Kind - 获取类型种类
  • func (v Value) Type() Type - 获取类型

基本类型获取

  • func (v Value) Bool() bool
  • func (v Value) Int() int64
  • func (v Value) Uint() uint64
  • func (v Value) Float() float64
  • func (v Value) Complex() complex128
  • func (v Value) String() string
  • func (v Value) Bytes() []byte
  • func (v Value) Interface() interface{}

复合类型操作

  • func (v Value) Len() int - 长度
  • func (v Value) Cap() int - 容量
  • func (v Value) Index(i int) Value - 索引访问
  • func (v Value) Field(i int) Value - 字段访问
  • func (v Value) FieldByName(name string) Value - 按名称访问字段
  • func (v Value) FieldByIndex(index []int) Value - 按索引访问字段
  • func (v Value) MapIndex(key Value) Value - map 索引
  • func (v Value) MapKeys() []Value - map 所有键
  • func (v Value) MapRange() *MapIter - map 迭代器

设置值

  • func (v Value) Set(x Value) - 设置值
  • func (v Value) SetBool(x bool)
  • func (v Value) SetInt(x int64)
  • func (v Value) SetUint(x uint64)
  • func (v Value) SetFloat(x float64)
  • func (v Value) SetComplex(x complex128)
  • func (v Value) SetString(x string)
  • func (v Value) SetBytes(x []byte)
  • func (v Value) SetCap(n int)
  • func (v Value) SetLen(n int)

方法调用

  • func (v Value) Call(in []Value) []Value - 调用函数
  • func (v Value) CallSlice(in []Value) []Value - 调用变参函数
  • func (v Value) Method(i int) Value - 获取方法
  • func (v Value) MethodByName(name string) Value - 按名称获取方法

类型转换

  • func (v Value) Convert(t Type) Value - 类型转换
  • func (v Value) Elem() Value - 获取元素
  • func (v Value) Pointer() uintptr - 获取指针

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x int = 42
    v := reflect.ValueOf(x)
    
    fmt.Println("Kind:", v.Kind())
    fmt.Println("Int:", v.Int())
    fmt.Println("Type:", v.Type())
    fmt.Println("IsValid:", v.IsValid())
    fmt.Println("CanSet:", v.CanSet())
}

运行结果

Kind: int
Int: 42
Type: int
IsValid: true
CanSet: false

ValueError

ValueError 表示方法调用中的错误。

type ValueError struct {
    Method string
    Kind   Kind
}

方法

  • func (e *ValueError) Error() string

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var v reflect.Value // 零值 Value
    
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Panic:", r)
        }
    }()
    
    // 调用零值 Value 的方法会 panic
    v.Int()
}

运行结果

Panic: reflect: call of reflect.Value.Int on zero Value

函数详解

ArrayOf

func ArrayOf(count int, elem Type) Type

说明:返回表示 elem[count] 的类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    arrayType := reflect.ArrayOf(5, intType)
    fmt.Println(arrayType) // [5]int
}

运行结果

[5]int

ChanOf

func ChanOf(dir ChanDir, t Type) Type

说明:返回表示指定方向的通道类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    
    sendChan := reflect.ChanOf(reflect.SendDir, intType)
    recvChan := reflect.ChanOf(reflect.RecvDir, intType)
    bothChan := reflect.ChanOf(reflect.BothDir, intType)
    
    fmt.Println(sendChan)   // chan<- int
    fmt.Println(recvChan)   // <-chan int
    fmt.Println(bothChan)   // chan int
}

运行结果

chan<- int
<-chan int
chan int

Copy

func Copy(dst, src Value) int

说明:将 src 复制到 dst,返回复制的元素数量。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    src := []int{1, 2, 3, 4, 5}
    dst := make([]int, 3)
    
    srcVal := reflect.ValueOf(src)
    dstVal := reflect.ValueOf(dst)
    
    n := reflect.Copy(dstVal, srcVal)
    fmt.Printf("Copied %d elements: %v\n", n, dstVal.Interface())
}

运行结果

Copied 3 elements: [1 2 3]

DeepEqual

func DeepEqual(x, y interface{}) bool

说明:递归比较两个值是否相等。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    type Person struct {
        Name string
        Age  int
    }
    
    p1 := Person{"Alice", 30}
    p2 := Person{"Alice", 30}
    p3 := Person{"Bob", 25}
    
    fmt.Println("p1 == p2:", reflect.DeepEqual(p1, p2))
    fmt.Println("p1 == p3:", reflect.DeepEqual(p1, p3))
    
    // 比较 map
    m1 := map[string]int{"a": 1, "b": 2}
    m2 := map[string]int{"b": 2, "a": 1}
    fmt.Println("m1 == m2:", reflect.DeepEqual(m1, m2))
}

运行结果

p1 == p2: true
p1 == p3: false
m1 == m2: true

FuncOf

func FuncOf(in, out []Type, variadic bool) Type

说明:返回表示函数类型的类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    stringType := reflect.TypeOf("")
    
    // func(int, int) string
    funcType := reflect.FuncOf(
        []reflect.Type{intType, intType},
        []reflect.Type{stringType},
        false,
    )
    
    fmt.Println(funcType)
}

运行结果

func(int, int) string

MakeChan

func MakeChan(typ Type, buffer int) Value

说明:创建新的通道。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    chanType := reflect.ChanOf(reflect.BothDir, intType)
    
    ch := reflect.MakeChan(chanType, 10)
    fmt.Printf("Channel: %v, Type: %v\n", ch, ch.Type())
}

运行结果

Channel: <chan Value>, Type: chan int

MakeFunc

func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value

说明:创建新的函数值。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    funcType := reflect.FuncOf(
        []reflect.Type{intType, intType},
        []reflect.Type{intType},
        false,
    )
    
    // 创建加法函数
    addFunc := reflect.MakeFunc(funcType, func(args []reflect.Value) []reflect.Value {
        a := args[0].Int()
        b := args[1].Int()
        return []reflect.Value{reflect.ValueOf(a + b)}
    })
    
    // 调用函数
    results := addFunc.Call([]reflect.Value{
        reflect.ValueOf(10),
        reflect.ValueOf(20),
    })
    
    fmt.Println("Result:", results[0].Int())
}

运行结果

Result: 30

MakeMap

func MakeMap(typ Type) Value

说明:创建新的 map。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    stringType := reflect.TypeOf("")
    intType := reflect.TypeOf(int(0))
    mapType := reflect.MapOf(stringType, intType)
    
    m := reflect.MakeMap(mapType)
    
    // 添加元素
    m.SetMapIndex(reflect.ValueOf("a"), reflect.ValueOf(1))
    m.SetMapIndex(reflect.ValueOf("b"), reflect.ValueOf(2))
    
    fmt.Printf("Map: %v\n", m.Interface())
}

运行结果

Map: map[a:1 b:2]

MakeSlice

func MakeSlice(typ Type, len, cap int) Value

说明:创建新的 slice。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    sliceType := reflect.SliceOf(intType)
    
    s := reflect.MakeSlice(sliceType, 5, 10)
    
    // 设置值
    for i := 0; i < s.Len(); i++ {
        s.Index(i).SetInt(int64(i * 10))
    }
    
    fmt.Printf("Slice: %v\n", s.Interface())
}

运行结果

Slice: [0 10 20 30 40]

MapOf

func MapOf(key, elem Type) Type

说明:返回表示 map[key]elem 的类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    stringType := reflect.TypeOf("")
    intType := reflect.TypeOf(int(0))
    
    mapType := reflect.MapOf(stringType, intType)
    fmt.Println(mapType) // map[string]int
}

运行结果

map[string]int

New

func New(typ Type) Value

说明:创建新的指针类型值。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    
    ptr := reflect.New(intType)
    fmt.Printf("Type: %v, Value: %v\n", ptr.Type(), ptr.Elem())
    
    // 设置值
    ptr.Elem().SetInt(42)
    fmt.Printf("Value after set: %v\n", ptr.Elem().Int())
}

运行结果

Type: *int, Value: 0
Value after set: 42

NewAt

func NewAt(typ Type, p unsafe.Pointer) Value

说明:类似 New,但使用提供的指针。

使用示例

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

func main() {
    var x int = 42
    
    ptr := reflect.NewAt(reflect.TypeOf(x), unsafe.Pointer(&x))
    fmt.Printf("Value: %v\n", ptr.Elem().Int())
    
    // 修改值
    ptr.Elem().SetInt(100)
    fmt.Printf("Modified x: %d\n", x)
}

运行结果

Value: 42
Modified x: 100

PointerTo

func PointerTo(t Type) Type

说明:返回表示 *t 的类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    ptrType := reflect.PointerTo(intType)
    
    fmt.Println(ptrType) // *int
}

运行结果

*int

Select

func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool)

说明:执行 select 语句。

使用示例

package main

import (
    "fmt"
    "reflect"
    "time"
)

func main() {
    ch1 := make(chan int, 1)
    ch2 := make(chan string, 1)
    
    go func() {
        time.Sleep(100 * time.Millisecond)
        ch1 <- 42
    }()
    
    cases := []reflect.SelectCase{
        {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch1)},
        {Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch2)},
    }
    
    chosen, recv, ok := reflect.Select(cases)
    fmt.Printf("chosen: %d, recv: %v, ok: %v\n", chosen, recv, ok)
}

运行结果

chosen: 0, recv: 42, ok: true

SliceOf

func SliceOf(t Type) Type

说明:返回表示 []t 的类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    sliceType := reflect.SliceOf(intType)
    
    fmt.Println(sliceType) // []int
}

运行结果

[]int

StructOf

func StructOf(fields []StructField) Type

说明:返回表示结构体类型的类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    fields := []reflect.StructField{
        {Name: "Name", Type: reflect.TypeOf("")},
        {Name: "Age", Type: reflect.TypeOf(int(0))},
    }
    
    structType := reflect.StructOf(fields)
    fmt.Println(structType) // struct { Name string; Age int }
}

运行结果

struct { Name string; Age int }

Swapper

func Swapper(slice interface{}) func(i, j int)

说明:返回一个函数,用于交换 slice 的两个元素。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
    swap := reflect.Swapper(s)
    
    fmt.Println("Before:", s)
    swap(0, 4)
    swap(1, 3)
    fmt.Println("After:", s)
}

运行结果

Before: [1 2 3 4 5]
After: [5 4 3 2 1]

TypeAssert

func TypeAssert(v Value, t Type) (x Value, ok bool)

说明:返回类型断言 v.(t) 的结果。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x interface{} = 42
    v := reflect.ValueOf(x)
    
    intType := reflect.TypeOf(int(0))
    result, ok := reflect.TypeAssert(v, intType)
    
    fmt.Printf("ok: %v, value: %v\n", ok, result.Int())
    
    stringType := reflect.TypeOf("")
    result2, ok2 := reflect.TypeAssert(v, stringType)
    fmt.Printf("ok: %v, valid: %v\n", ok2, result2.IsValid())
}

运行结果

ok: true, value: 42
ok: false, valid: false

TypeOf

func TypeOf(i interface{}) Type

说明:返回接口值的类型。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x int = 42
    var y float64 = 3.14
    var z = "hello"
    
    fmt.Println("x type:", reflect.TypeOf(x))
    fmt.Println("y type:", reflect.TypeOf(y))
    fmt.Println("z type:", reflect.TypeOf(z))
}

运行结果

x type: int
y type: float64
z type: string

ValueOf

func ValueOf(i interface{}) Value

说明:返回接口值的 Value 实例。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x int = 42
    
    v := reflect.ValueOf(x)
    fmt.Printf("Kind: %s, Int: %d\n", v.Kind(), v.Int())
    
    // 可寻址的值
    y := 100
    vy := reflect.ValueOf(&y).Elem()
    vy.SetInt(200)
    fmt.Printf("Modified y: %d\n", y)
}

运行结果

Kind: int, Int: 42
Modified y: 200

Zero

func Zero(typ Type) Value

说明:返回类型的零值。

使用示例

package main

import (
    "fmt"
    "reflect"
)

func main() {
    intType := reflect.TypeOf(int(0))
    zeroInt := reflect.Zero(intType)
    
    fmt.Printf("Zero int: %d\n", zeroInt.Int())
    
    stringType := reflect.TypeOf("")
    zeroString := reflect.Zero(stringType)
    
    fmt.Printf("Zero string: %q\n", zeroString.String())
}

运行结果

Zero int: 0
Zero string: ""

典型示例

示例 1:动态类型检查

package main

import (
    "fmt"
    "reflect"
)

func inspectType(value interface{}) {
    t := reflect.TypeOf(value)
    v := reflect.ValueOf(value)
    
    fmt.Printf("Type: %s, Kind: %s\n", t.Name(), t.Kind())
    
    switch v.Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        fmt.Printf("  Integer value: %d\n", v.Int())
    case reflect.Float32, reflect.Float64:
        fmt.Printf("  Float value: %f\n", v.Float())
    case reflect.String:
        fmt.Printf("  String value: %s\n", v.String())
    case reflect.Slice:
        fmt.Printf("  Slice length: %d\n", v.Len())
    case reflect.Map:
        fmt.Printf("  Map length: %d\n", v.Len())
    }
}

func main() {
    inspectType(42)
    inspectType(3.14)
    inspectType("hello")
    inspectType([]int{1, 2, 3})
    inspectType(map[string]int{"a": 1})
}

运行结果

Type: int, Kind: int
  Integer value: 42
Type: float64, Kind: float64
  Float value: 3.140000
Type: string, Kind: string
  String value: hello
Type: , Kind: slice
  Slice length: 3
Type: , Kind: map
  Map length: 1

示例 2:结构体字段遍历

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name  string `json:"name" db:"user_name"`
    Age   int    `json:"age" db:"user_age"`
    Email string `json:"email" db:"user_email"`
}

func printStructTags(value interface{}) {
    t := reflect.TypeOf(value)
    
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        jsonTag := field.Tag.Get("json")
        dbTag := field.Tag.Get("db")
        
        fmt.Printf("Field: %s, JSON: %s, DB: %s\n", 
            field.Name, jsonTag, dbTag)
    }
}

func main() {
    p := Person{
        Name:  "Alice",
        Age:   30,
        Email: "alice@example.com",
    }
    
    printStructTags(p)
}

运行结果

Field: Name, JSON: name, DB: user_name
Field: Age, JSON: age, DB: user_age
Field: Email, JSON: email, DB: user_email

示例 3:动态调用方法

package main

import (
    "fmt"
    "reflect"
)

type Calculator struct {
    value int
}

func (c *Calculator) Add(n int) {
    c.value += n
    fmt.Printf("Add %d, result: %d\n", n, c.value)
}

func (c *Calculator) Subtract(n int) {
    c.value -= n
    fmt.Printf("Subtract %d, result: %d\n", n, c.value)
}

func (c *Calculator) Multiply(n int) {
    c.value *= n
    fmt.Printf("Multiply %d, result: %d\n", n, c.value)
}

func callMethod(obj interface{}, methodName string, args ...interface{}) {
    v := reflect.ValueOf(obj)
    method := v.MethodByName(methodName)
    
    if !method.IsValid() {
        fmt.Printf("Method %s not found\n", methodName)
        return
    }
    
    in := make([]reflect.Value, len(args))
    for i, arg := range args {
        in[i] = reflect.ValueOf(arg)
    }
    
    method.Call(in)
}

func main() {
    calc := &Calculator{value: 10}
    
    callMethod(calc, "Add", 5)
    callMethod(calc, "Multiply", 3)
    callMethod(calc, "Subtract", 10)
}

运行结果

Add 5, result: 15
Multiply 3, result: 45
Subtract 10, result: 35

示例 4:通用 JSON 标签解析

package main

import (
    "fmt"
    "reflect"
    "strings"
)

type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Email    string `json:"email,omitempty"`
    Age      int    `json:"age,omitempty"`
}

func parseJSONTags(value interface{}) map[string]string {
    result := make(map[string]string)
    
    v := reflect.ValueOf(value)
    t := reflect.TypeOf(value)
    
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        fieldValue := v.Field(i)
        
        jsonTag := field.Tag.Get("json")
        if jsonTag == "" || jsonTag == "-" {
            continue
        }
        
        // 解析标签(处理 omitempty 等选项)
        parts := strings.Split(jsonTag, ",")
        fieldName := parts[0]
        
        // 跳过 omitempty 字段的零值
        if len(parts) > 1 && parts[1] == "omitempty" && fieldValue.IsZero() {
            continue
        }
        
        result[fieldName] = fmt.Sprintf("%v", fieldValue.Interface())
    }
    
    return result
}

func main() {
    user := User{
        ID:       1,
        Username: "alice",
        Email:    "alice@example.com",
        Age:      0, // omitempty 字段
    }
    
    parsed := parseJSONTags(user)
    
    for k, v := range parsed {
        fmt.Printf("%s: %s\n", k, v)
    }
}

运行结果

id: 1
username: alice
email: alice@example.com

示例 5:动态创建结构体

package main

import (
    "fmt"
    "reflect"
)

func createStruct(fields map[string]interface{}) interface{} {
    structFields := make([]reflect.StructField, 0, len(fields))
    
    for name, value := range fields {
        structFields = append(structFields, reflect.StructField{
            Name: name,
            Type: reflect.TypeOf(value),
            Tag:  reflect.StructTag(fmt.Sprintf(`json:"%s"`, name)),
        })
    }
    
    structType := reflect.StructOf(structFields)
    structValue := reflect.New(structType).Elem()
    
    for i, field := range structFields {
        structValue.Field(i).Set(reflect.ValueOf(fields[field.Name]))
    }
    
    return structValue.Interface()
}

func main() {
    data := map[string]interface{}{
        "Name": "Alice",
        "Age":  30,
        "City": "New York",
    }
    
    obj := createStruct(data)
    fmt.Printf("Type: %T\n", obj)
    fmt.Printf("Value: %+v\n", obj)
}

运行结果

Type: struct { Age int; City string; Name string }
Value: {Age:30 City:New York Name:Alice}

示例 6:深度复制

package main

import (
    "fmt"
    "reflect"
)

func deepCopy(dst, src interface{}) {
    dstVal := reflect.ValueOf(dst).Elem()
    srcVal := reflect.ValueOf(src)
    
    if dstVal.Type() != srcVal.Type() {
        panic("类型不匹配")
    }
    
    copyValue(dstVal, srcVal)
}

func copyValue(dst, src reflect.Value) {
    switch src.Kind() {
    case reflect.Ptr:
        dst.Set(reflect.New(src.Type().Elem()))
        copyValue(dst.Elem(), src.Elem())
        
    case reflect.Struct:
        for i := 0; i < src.NumField(); i++ {
            copyValue(dst.Field(i), src.Field(i))
        }
        
    case reflect.Slice:
        dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap()))
        for i := 0; i < src.Len(); i++ {
            copyValue(dst.Index(i), src.Index(i))
        }
        
    case reflect.Map:
        dst.Set(reflect.MakeMap(src.Type()))
        for _, key := range src.MapKeys() {
            val := reflect.New(src.Type().Elem()).Elem()
            copyValue(val, src.MapIndex(key))
            dst.SetMapIndex(key, val)
        }
        
    default:
        dst.Set(src)
    }
}

func main() {
    type Person struct {
        Name    string
        Friends []string
        Address struct {
            City string
        }
    }
    
    original := Person{
        Name:    "Alice",
        Friends: []string{"Bob", "Charlie"},
    }
    original.Address.City = "New York"
    
    var copy Person
    deepCopy(&copy, original)
    
    fmt.Printf("Original: %+v\n", original)
    fmt.Printf("Copy: %+v\n", copy)
    
    // 修改副本不影响原值
    copy.Friends[0] = "David"
    fmt.Printf("After modification:\n")
    fmt.Printf("Original: %+v\n", original)
    fmt.Printf("Copy: %+v\n", copy)
}

运行结果

Original: {Name:Alice Friends:[Bob Charlie] Address:{City:New York}}
Copy: {Name:Alice Friends:[Bob Charlie] Address:{City:New York}}
After modification:
Original: {Name:Alice Friends:[Bob Charlie] Address:{City:New York}}
Copy: {Name:Alice Friends:[David Charlie] Address:{City:New York}}

示例 7:通用排序

package main

import (
    "fmt"
    "reflect"
)

func sortSlice(slice interface{}, less func(i, j int) bool) {
    v := reflect.ValueOf(slice)
    
    if v.Kind() != reflect.Slice {
        panic("必须是 slice")
    }
    
    swap := reflect.Swapper(slice)
    
    // 简单冒泡排序
    n := v.Len()
    for i := 0; i < n-1; i++ {
        for j := 0; j < n-i-1; j++ {
            if less(j, j+1) {
                swap(j, j+1)
            }
        }
    }
}

func main() {
    // 排序整数
    nums := []int{5, 2, 8, 1, 9}
    sortSlice(nums, func(i, j int) bool {
        return nums[i] < nums[j]
    })
    fmt.Println("Sorted nums:", nums)
    
    // 排序字符串
    strs := []string{"banana", "apple", "cherry"}
    sortSlice(strs, func(i, j int) bool {
        return strs[i] < strs[j]
    })
    fmt.Println("Sorted strs:", strs)
    
    // 排序结构体
    type Person struct {
        Name string
        Age  int
    }
    
    people := []Person{
        {"Alice", 30},
        {"Bob", 25},
        {"Charlie", 35},
    }
    
    sortSlice(people, func(i, j int) bool {
        return people[i].Age < people[j].Age
    })
    
    fmt.Println("Sorted people:")
    for _, p := range people {
        fmt.Printf("  %s (%d)\n", p.Name, p.Age)
    }
}

运行结果

Sorted nums: [1 2 5 8 9]
Sorted strs: [apple banana cherry]
Sorted people:
  Bob (25)
  Alice (30)
  Charlie (35)

示例 8:动态验证器

package main

import (
    "fmt"
    "reflect"
    "strings"
    "unicode/utf8"
)

type Validator struct {
    errors []string
}

func (v *Validator) validateField(field reflect.Value, tag string) {
    parts := strings.Split(tag, ",")
    
    for _, part := range parts {
        switch {
        case part == "required":
            if field.IsZero() {
                v.errors = append(v.errors, "字段不能为空")
            }
            
        case strings.HasPrefix(part, "min="):
            var min int
            fmt.Sscanf(part[4:], "%d", &min)
            
            switch field.Kind() {
            case reflect.String:
                if utf8.RuneCountInString(field.String()) < min {
                    v.errors = append(v.errors, fmt.Sprintf("最小长度为 %d", min))
                }
            case reflect.Int, reflect.Int64:
                if field.Int() < int64(min) {
                    v.errors = append(v.errors, fmt.Sprintf("最小值为 %d", min))
                }
            }
            
        case strings.HasPrefix(part, "max="):
            var max int
            fmt.Sscanf(part[4:], "%d", &max)
            
            switch field.Kind() {
            case reflect.String:
                if utf8.RuneCountInString(field.String()) > max {
                    v.errors = append(v.errors, fmt.Sprintf("最大长度为 %d", max))
                }
            }
        }
    }
}

func (v *Validator) Validate(value interface{}) []string {
    v.errors = []string{}
    
    val := reflect.ValueOf(value)
    typ := reflect.TypeOf(value)
    
    for i := 0; i < val.NumField(); i++ {
        field := val.Field(i)
        fieldTyp := typ.Field(i)
        
        validateTag := fieldTyp.Tag.Get("validate")
        if validateTag != "" {
            v.validateField(field, validateTag)
        }
    }
    
    return v.errors
}

type User struct {
    Username string `validate:"required,min=3,max=20"`
    Age      int    `validate:"min=18"`
    Email    string `validate:"required"`
}

func main() {
    validator := &Validator{}
    
    user := User{
        Username: "ab",     // 太短
        Age:      16,       // 未成年
        Email:    "",       // 空
    }
    
    errors := validator.Validate(user)
    
    if len(errors) > 0 {
        fmt.Println("验证失败:")
        for _, err := range errors {
            fmt.Printf("  - %s\n", err)
        }
    } else {
        fmt.Println("验证通过")
    }
}

运行结果

验证失败:
  - 字段不能为空
  - 最小长度为 3
  - 最小值为 18
  - 字段不能为空

最佳实践

1. 优先使用类型断言

// ❌ 不推荐:过度使用反射
func process(value interface{}) {
    v := reflect.ValueOf(value)
    if v.Kind() == reflect.String {
        s := v.String()
        // ...
    }
}

// ✅ 推荐:使用类型断言
func process(value interface{}) {
    if s, ok := value.(string); ok {
        // ...
    }
}

2. 缓存反射结果

// ❌ 不推荐:重复反射
func process(items []interface{}) {
    for _, item := range items {
        t := reflect.TypeOf(item)
        // 每次都重新计算
    }
}

// ✅ 推荐:缓存类型信息
var typeCache = make(map[reflect.Type]bool)

func process(items []interface{}) {
    for _, item := range items {
        t := reflect.TypeOf(item)
        if cached, ok := typeCache[t]; ok {
            // 使用缓存
        }
    }
}

3. 使用指针以便修改

// ❌ 错误:无法修改
func setValue(value interface{}) {
    v := reflect.ValueOf(value)
    v.SetInt(42) // panic!
}

// ✅ 正确:传递指针
func setValue(value interface{}) {
    v := reflect.ValueOf(value)
    if v.Kind() == reflect.Ptr {
        v.Elem().SetInt(42)
    }
}

// 调用
var x int
setValue(&x)

4. 检查有效性

// ✅ 推荐:始终检查
func safeProcess(value reflect.Value) {
    if !value.IsValid() {
        return
    }
    
    if !value.CanSet() {
        return
    }
    
    // 安全操作
}

5. 使用标签系统

type User struct {
    Name  string `json:"name" validate:"required,min=3"`
    Email string `json:"email" validate:"required,email"`
    Age   int    `json:"age" validate:"min=18"`
}

与其他包配合

encoding/json

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    p := Person{"Alice", 30}
    
    // JSON 序列化
    data, _ := json.Marshal(p)
    fmt.Println("JSON:", string(data))
    
    // 使用反射检查标签
    t := reflect.TypeOf(p)
    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        jsonTag := field.Tag.Get("json")
        fmt.Printf("%s -> %s\n", field.Name, jsonTag)
    }
}

database/sql

package main

import (
    "database/sql"
    "fmt"
    "reflect"
)

type User struct {
    ID    int    `db:"id"`
    Name  string `db:"name"`
    Email string `db:"email"`
}

func scanStruct(rows *sql.Rows, dest interface{}) error {
    v := reflect.ValueOf(dest).Elem()
    t := v.Type()
    
    columns, _ := rows.Columns()
    values := make([]interface{}, len(columns))
    
    for i := range values {
        values[i] = new(interface{})
    }
    
    if err := rows.Scan(values...); err != nil {
        return err
    }
    
    for i, col := range columns {
        for j := 0; j < t.NumField(); j++ {
            field := t.Field(j)
            dbTag := field.Tag.Get("db")
            
            if dbTag == col {
                val := *(values[i].(*interface{}))
                v.Field(j).Set(reflect.ValueOf(val))
                break
            }
        }
    }
    
    return nil
}

快速参考

常量

常量类型说明
PtrChanDir已弃用,ChanDir 的旧名称

类型

类型说明方法数
ChanDir通道方向-
Kind类型种类(25 种)-
MapItermap 迭代器3
Method方法信息-
SelectCaseselect 案例-
SelectDirselect 方向-
SliceHeader已弃用-
StringHeader已弃用-
StructField结构体字段-
StructTag结构体标签2
Type类型表示30+
Value值表示60+
ValueError值错误1

函数

函数参数返回值说明
ArrayOfcount int, elem TypeType创建数组类型
ChanOfdir ChanDir, t TypeType创建通道类型
Copydst, src Valueint复制 slice
DeepEqualx, y interface{}bool深度比较
FuncOfin, out []Type, variadic boolType创建函数类型
MakeChantyp Type, buffer intValue创建通道
MakeFunctyp Type, fn funcValue创建函数
MakeMaptyp TypeValue创建 map
MakeSlicetyp Type, len, cap intValue创建 slice
MapOfkey, elem TypeType创建 map 类型
Newtyp TypeValue创建指针
NewAttyp Type, p unsafe.PointerValue创建指针(指定地址)
PointerTot TypeType创建指针类型
Selectcases []SelectCasechosen, recv, ok执行 select
SliceOft TypeType创建 slice 类型
StructOffields []StructFieldType创建结构体类型
Swapperslice interface{}func返回交换函数
TypeAssertv Value, t Typex, ok类型断言
TypeOfi interface{}Type获取类型
ValueOfi interface{}Value获取值
Zerotyp TypeValue零值

注意事项

1. 性能考虑

反射比直接代码慢 10-100 倍:

// ❌ 慢:使用反射
func sumReflect(values []int) int {
    v := reflect.ValueOf(values)
    sum := 0
    for i := 0; i < v.Len(); i++ {
        sum += int(v.Index(i).Int())
    }
    return sum
}

// ✅ 快:直接访问
func sumDirect(values []int) int {
    sum := 0
    for _, v := range values {
        sum += v
    }
    return sum
}

2. 类型安全

反射绕过类型检查,容易出错:

// ❌ 危险:运行时错误
func dangerous(value interface{}) {
    v := reflect.ValueOf(value)
    v.SetInt(42) // 如果 value 不是可设置的 int,会 panic
}

// ✅ 安全:先检查
func safe(value interface{}) error {
    v := reflect.ValueOf(value)
    
    if !v.IsValid() {
        return fmt.Errorf("无效值")
    }
    
    if v.Kind() != reflect.Int {
        return fmt.Errorf("必须是 int 类型")
    }
    
    if !v.CanSet() {
        return fmt.Errorf("值不可设置")
    }
    
    v.SetInt(42)
    return nil
}

3. 可寻址性

只有可寻址的值才能修改:

// ❌ 错误
x := 42
v := reflect.ValueOf(x)
v.SetInt(100) // panic: not settable

// ✅ 正确
x := 42
v := reflect.ValueOf(&x).Elem()
v.SetInt(100) // 成功

4. 零值 Value

未初始化的 Value 调用方法会 panic:

var v reflect.Value
v.Int() // panic: reflect: call of reflect.Value.Int on zero Value

// ✅ 检查
if !v.IsValid() {
    // 处理零值
}

5. Bugs

根据官方文档,已知问题:

  • FieldByName 和相关函数可能返回不正确的结果,当结构体有多个同名字段时
  • 某些边缘情况下的行为可能不符合预期

6. 平台限制

  • 反射代码难以被编译器优化
  • 某些反射操作可能在某些平台上行为不同

7. 调试困难

反射错误通常在运行时才暴露,难以调试。

总结

reflect 包是 Go 最强大的包之一,提供了运行时类型检查和值操作能力。它被广泛应用于:

  • JSON/XML 序列化和反序列化
  • ORM 框架
  • 验证框架
  • 模板引擎
  • 测试框架
  • RPC 框架

使用原则

  1. 只在必要时使用反射
  2. 优先使用类型断言和接口
  3. 缓存反射结果
  4. 始终检查有效性和可设置性
  5. 提供清晰的错误信息

记住反射三定律

  1. 反射从接口值到反射对象
  2. 反射从反射对象到接口值
  3. 要修改反射对象,值必须是可设置的