Go reflect 包详解
概述
reflect 包实现了运行时反射,允许程序通过任意类型的值来检查其类型和值。它提供了强大的动态类型检查和操作能力。
重要提示:反射虽然强大,但应该谨慎使用。过度使用反射会导致代码难以理解和维护,性能也会下降。
反射三定律:
- Reflection goes from interface value to reflection object(反射从接口值到反射对象)
- Reflection goes from reflection object to interface value(反射从反射对象到接口值)
- To modify a reflection object, the value must be settable(要修改反射对象,值必须是可设置的)
包导入
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
说明:Ptr 是 ChanDir 的旧名称,已弃用,仅为兼容保留。
使用示例:
// 不推荐使用,直接使用 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- 值是否为 nilfunc (v Value) CanAddr() bool- 值是否可寻址func (v Value) CanSet() bool- 值是否可设置func (v Value) Kind() Kind- 获取类型种类func (v Value) Type() Type- 获取类型
基本类型获取:
func (v Value) Bool() boolfunc (v Value) Int() int64func (v Value) Uint() uint64func (v Value) Float() float64func (v Value) Complex() complex128func (v Value) String() stringfunc (v Value) Bytes() []bytefunc (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(©, 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
}
快速参考
常量
| 常量 | 类型 | 说明 |
|---|---|---|
| Ptr | ChanDir | 已弃用,ChanDir 的旧名称 |
类型
| 类型 | 说明 | 方法数 |
|---|---|---|
| ChanDir | 通道方向 | - |
| Kind | 类型种类(25 种) | - |
| MapIter | map 迭代器 | 3 |
| Method | 方法信息 | - |
| SelectCase | select 案例 | - |
| SelectDir | select 方向 | - |
| SliceHeader | 已弃用 | - |
| StringHeader | 已弃用 | - |
| StructField | 结构体字段 | - |
| StructTag | 结构体标签 | 2 |
| Type | 类型表示 | 30+ |
| Value | 值表示 | 60+ |
| ValueError | 值错误 | 1 |
函数
| 函数 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| ArrayOf | count int, elem Type | Type | 创建数组类型 |
| ChanOf | dir ChanDir, t Type | Type | 创建通道类型 |
| Copy | dst, src Value | int | 复制 slice |
| DeepEqual | x, y interface{} | bool | 深度比较 |
| FuncOf | in, out []Type, variadic bool | Type | 创建函数类型 |
| MakeChan | typ Type, buffer int | Value | 创建通道 |
| MakeFunc | typ Type, fn func | Value | 创建函数 |
| MakeMap | typ Type | Value | 创建 map |
| MakeSlice | typ Type, len, cap int | Value | 创建 slice |
| MapOf | key, elem Type | Type | 创建 map 类型 |
| New | typ Type | Value | 创建指针 |
| NewAt | typ Type, p unsafe.Pointer | Value | 创建指针(指定地址) |
| PointerTo | t Type | Type | 创建指针类型 |
| Select | cases []SelectCase | chosen, recv, ok | 执行 select |
| SliceOf | t Type | Type | 创建 slice 类型 |
| StructOf | fields []StructField | Type | 创建结构体类型 |
| Swapper | slice interface{} | func | 返回交换函数 |
| TypeAssert | v Value, t Type | x, ok | 类型断言 |
| TypeOf | i interface{} | Type | 获取类型 |
| ValueOf | i interface{} | Value | 获取值 |
| Zero | typ Type | Value | 零值 |
注意事项
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 框架
使用原则:
- 只在必要时使用反射
- 优先使用类型断言和接口
- 缓存反射结果
- 始终检查有效性和可设置性
- 提供清晰的错误信息
记住反射三定律:
- 反射从接口值到反射对象
- 反射从反射对象到接口值
- 要修改反射对象,值必须是可设置的