package main
import (
"fmt"
"reflect"
"time"
)
// 定义一个结构体
type Person struct {
Name string
Age int
}
// 常规方式读取结构体字段
func readFieldConventional(p Person, field string) (interface{}, bool) {
switch field {
case "Name":
return p.Name, true
case "Age":
return p.Age, true
default:
return nil, false
}
}
// 常规方式修改结构体字段
func setFieldConventional(p *Person, field string, value interface{}) bool {
switch field {
case "Name":
if v, ok := value.(string); ok {
p.Name = v
return true
}
case "Age":
if v, ok := value.(int); ok {
p.Age = v
return true
}
default:
return false
}
return false
}
// 反射方式读取结构体字段
func readFieldReflect(p interface{}, field string) (interface{}, bool) {
valueOf := reflect.ValueOf(p)
if valueOf.Kind() == reflect.Ptr {
valueOf = valueOf.Elem()
}
fieldValue := valueOf.FieldByName(field)
if fieldValue.IsValid() {
return fieldValue.Interface(), true
}
return nil, false
}
// 反射方式修改结构体字段
func setFieldReflect(p interface{}, field string, value interface{}) bool {
valueOf := reflect.ValueOf(p)
if valueOf.Kind() != reflect.Ptr || valueOf.IsNil() {
return false
}
elem := valueOf.Elem()
fieldValue := elem.FieldByName(field)
if fieldValue.IsValid() && fieldValue.CanSet() {
valueValue := reflect.ValueOf(value)
if fieldValue.Type().AssignableTo(valueValue.Type()) {
fieldValue.Set(valueValue)
return true
}
}
return false
}
func main() {
p := Person{Name: "Alice", Age: 30}
// 常规方式性能测试
start := time.Now()
for i := 0; i < 1000000; i++ {
readFieldConventional(p, "Name")
setFieldConventional(&p, "Age", 31)
}
elapsedConventional := time.Since(start)
// 反射方式性能测试
start = time.Now()
for i := 0; i < 1000000; i++ {
readFieldReflect(p, "Name")
setFieldReflect(&p, "Age", 31)
}
elapsedReflect := time.Since(start)
fmt.Printf("常规方式耗时: %s\n", elapsedConventional)
fmt.Printf("反射方式耗时: %s\n", elapsedReflect)
if elapsedConventional < elapsedReflect {
fmt.Println("常规方式性能优于反射方式")
} else if elapsedConventional > elapsedReflect {
fmt.Println("反射方式性能优于常规方式")
} else {
fmt.Println("两者性能相当")
}
}
结果分析
- 常规方式:
- 优点:代码可读性高,逻辑直接,编译器可以在编译时进行类型检查,性能相对较好,因为它直接操作结构体字段,没有额外的运行时开销。
- 缺点:不够灵活,对于不同的结构体字段操作需要编写不同的逻辑,代码量会随着结构体字段的增加而增加。
- 反射方式:
- 优点:高度灵活,可以在运行时动态获取和修改结构体字段,适用于需要通用处理不同结构体的场景,例如序列化/反序列化库等。
- 缺点:性能开销较大,因为反射需要在运行时进行类型检查和查找,涉及到额外的内存访问和计算。从性能测试结果来看,反射方式耗时通常会比常规方式长,尤其是在大量操作的情况下。所以在性能敏感的场景中,应优先考虑常规方式,而在需要高度灵活性的场景中,反射方式是更好的选择。