Files
golang/golang-learning/09-advanced/01-reflection.go
2025-08-24 13:01:09 +08:00

968 lines
24 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
01-reflection.go - Go 语言反射详解
学习目标:
1. 理解反射的概念和原理
2. 掌握 reflect 包的基本使用
3. 学会反射的类型和值操作
4. 了解反射的应用场景
5. 掌握反射的最佳实践和注意事项
知识点:
- 反射的基本概念
- reflect.Type 和 reflect.Value
- 类型检查和转换
- 结构体字段和方法的反射
- 反射的性能考虑
- 反射的实际应用
*/
package main
import (
"fmt"
"reflect"
"strconv"
"strings"
"time"
)
func main() {
fmt.Println("=== Go 语言反射详解 ===\\n")
// 演示反射的基本概念
demonstrateReflectionBasics()
// 演示类型反射
demonstrateTypeReflection()
// 演示值反射
demonstrateValueReflection()
// 演示结构体反射
demonstrateStructReflection()
// 演示方法反射
demonstrateMethodReflection()
// 演示反射的实际应用
demonstratePracticalApplications()
// 演示反射的最佳实践
demonstrateBestPractices()
}
// demonstrateReflectionBasics 演示反射的基本概念
func demonstrateReflectionBasics() {
fmt.Println("1. 反射的基本概念:")
// 反射的基本概念
fmt.Printf(" 反射的基本概念:\\n")
fmt.Printf(" - 反射是程序在运行时检查自身结构的能力\\n")
fmt.Printf(" - Go 通过 reflect 包提供反射功能\\n")
fmt.Printf(" - 反射基于接口的动态类型信息\\n")
fmt.Printf(" - 主要包括类型反射和值反射\\n")
fmt.Printf(" - 反射遵循 Go 的类型系统规则\\n")
// 反射的核心类型
fmt.Printf(" 反射的核心类型:\\n")
fmt.Printf(" - reflect.Type: 表示类型信息\\n")
fmt.Printf(" - reflect.Value: 表示值信息\\n")
fmt.Printf(" - reflect.Kind: 表示基础类型种类\\n")
// 基本反射示例
fmt.Printf(" 基本反射示例:\\n")
var x interface{} = 42
// 获取类型信息
t := reflect.TypeOf(x)
fmt.Printf(" 类型: %v\\n", t)
fmt.Printf(" 类型名称: %s\\n", t.Name())
fmt.Printf(" 类型种类: %v\\n", t.Kind())
// 获取值信息
v := reflect.ValueOf(x)
fmt.Printf(" 值: %v\\n", v)
fmt.Printf(" 值的类型: %v\\n", v.Type())
fmt.Printf(" 值的种类: %v\\n", v.Kind())
fmt.Printf(" 值的接口: %v\\n", v.Interface())
// 不同类型的反射
fmt.Printf(" 不同类型的反射:\\n")
values := []interface{}{
42,
"hello",
3.14,
true,
[]int{1, 2, 3},
map[string]int{"a": 1},
Person{Name: "Alice", Age: 30},
}
for i, val := range values {
t := reflect.TypeOf(val)
v := reflect.ValueOf(val)
fmt.Printf(" 值%d: %v (类型: %v, 种类: %v)\\n",
i+1, val, t, v.Kind())
}
fmt.Println()
}
// demonstrateTypeReflection 演示类型反射
func demonstrateTypeReflection() {
fmt.Println("2. 类型反射:")
// 基本类型反射
fmt.Printf(" 基本类型反射:\\n")
var i int = 42
var s string = "hello"
var f float64 = 3.14
var b bool = true
types := []interface{}{i, s, f, b}
for _, val := range types {
t := reflect.TypeOf(val)
fmt.Printf(" %v: 名称=%s, 种类=%v, 大小=%d字节\\n",
val, t.Name(), t.Kind(), t.Size())
}
// 复合类型反射
fmt.Printf(" 复合类型反射:\\n")
// 切片类型
slice := []int{1, 2, 3}
sliceType := reflect.TypeOf(slice)
fmt.Printf(" 切片类型: %v\\n", sliceType)
fmt.Printf(" 元素类型: %v\\n", sliceType.Elem())
fmt.Printf(" 是否为切片: %t\\n", sliceType.Kind() == reflect.Slice)
// 映射类型
m := map[string]int{"a": 1, "b": 2}
mapType := reflect.TypeOf(m)
fmt.Printf(" 映射类型: %v\\n", mapType)
fmt.Printf(" 键类型: %v\\n", mapType.Key())
fmt.Printf(" 值类型: %v\\n", mapType.Elem())
// 指针类型
var p *int = &i
ptrType := reflect.TypeOf(p)
fmt.Printf(" 指针类型: %v\\n", ptrType)
fmt.Printf(" 指向类型: %v\\n", ptrType.Elem())
fmt.Printf(" 是否为指针: %t\\n", ptrType.Kind() == reflect.Ptr)
// 函数类型
fn := func(int, string) bool { return true }
fnType := reflect.TypeOf(fn)
fmt.Printf(" 函数类型: %v\\n", fnType)
fmt.Printf(" 参数个数: %d\\n", fnType.NumIn())
fmt.Printf(" 返回值个数: %d\\n", fnType.NumOut())
for i := 0; i < fnType.NumIn(); i++ {
fmt.Printf(" 参数%d类型: %v\\n", i, fnType.In(i))
}
for i := 0; i < fnType.NumOut(); i++ {
fmt.Printf(" 返回值%d类型: %v\\n", i, fnType.Out(i))
}
// 通道类型
ch := make(chan int)
chType := reflect.TypeOf(ch)
fmt.Printf(" 通道类型: %v\\n", chType)
fmt.Printf(" 通道方向: %v\\n", chType.ChanDir())
fmt.Printf(" 元素类型: %v\\n", chType.Elem())
fmt.Println()
}
// demonstrateValueReflection 演示值反射
func demonstrateValueReflection() {
fmt.Println("3. 值反射:")
// 基本值操作
fmt.Printf(" 基本值操作:\\n")
var x interface{} = 42
v := reflect.ValueOf(x)
fmt.Printf(" 原始值: %v\\n", v.Interface())
fmt.Printf(" 整数值: %d\\n", v.Int())
fmt.Printf(" 是否有效: %t\\n", v.IsValid())
fmt.Printf(" 是否为零值: %t\\n", v.IsZero())
// 值的修改
fmt.Printf(" 值的修改:\\n")
var y int = 100
v = reflect.ValueOf(&y) // 需要传递指针才能修改
if v.Kind() == reflect.Ptr && v.Elem().CanSet() {
v.Elem().SetInt(200)
fmt.Printf(" 修改后的值: %d\\n", y)
}
// 字符串值操作
var str string = "hello"
v = reflect.ValueOf(&str)
if v.Kind() == reflect.Ptr && v.Elem().CanSet() {
v.Elem().SetString("world")
fmt.Printf(" 修改后的字符串: %s\\n", str)
}
// 切片值操作
fmt.Printf(" 切片值操作:\\n")
slice := []int{1, 2, 3}
v = reflect.ValueOf(slice)
fmt.Printf(" 切片长度: %d\\n", v.Len())
fmt.Printf(" 切片容量: %d\\n", v.Cap())
// 访问切片元素
for i := 0; i < v.Len(); i++ {
elem := v.Index(i)
fmt.Printf(" 元素[%d]: %v\\n", i, elem.Interface())
}
// 映射值操作
fmt.Printf(" 映射值操作:\\n")
m := map[string]int{"a": 1, "b": 2, "c": 3}
v = reflect.ValueOf(m)
fmt.Printf(" 映射长度: %d\\n", v.Len())
// 遍历映射
for _, key := range v.MapKeys() {
value := v.MapIndex(key)
fmt.Printf(" %v: %v\\n", key.Interface(), value.Interface())
}
// 设置映射值
v.SetMapIndex(reflect.ValueOf("d"), reflect.ValueOf(4))
fmt.Printf(" 添加元素后: %v\\n", m)
// 创建新值
fmt.Printf(" 创建新值:\\n")
// 创建新的整数值
newInt := reflect.New(reflect.TypeOf(0))
newInt.Elem().SetInt(999)
fmt.Printf(" 新创建的整数: %v\\n", newInt.Elem().Interface())
// 创建新的切片
sliceType := reflect.SliceOf(reflect.TypeOf(0))
newSlice := reflect.MakeSlice(sliceType, 3, 5)
for i := 0; i < newSlice.Len(); i++ {
newSlice.Index(i).SetInt(int64(i * 10))
}
fmt.Printf(" 新创建的切片: %v\\n", newSlice.Interface())
fmt.Println()
}
// demonstrateStructReflection 演示结构体反射
func demonstrateStructReflection() {
fmt.Println("4. 结构体反射:")
// 结构体类型信息
fmt.Printf(" 结构体类型信息:\\n")
person := Person{
Name: "Alice",
Age: 30,
Email: "alice@example.com",
}
t := reflect.TypeOf(person)
v := reflect.ValueOf(person)
fmt.Printf(" 结构体名称: %s\\n", t.Name())
fmt.Printf(" 字段数量: %d\\n", t.NumField())
// 遍历结构体字段
fmt.Printf(" 遍历结构体字段:\\n")
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf(" 字段%d: %s (类型: %v, 值: %v)\\n",
i, field.Name, field.Type, value.Interface())
// 检查字段标签
if tag := field.Tag; tag != "" {
fmt.Printf(" 标签: %s\\n", tag)
if jsonTag := tag.Get("json"); jsonTag != "" {
fmt.Printf(" JSON标签: %s\\n", jsonTag)
}
}
}
// 按名称访问字段
fmt.Printf(" 按名称访问字段:\\n")
nameField := v.FieldByName("Name")
if nameField.IsValid() {
fmt.Printf(" Name字段值: %v\\n", nameField.Interface())
}
// 修改结构体字段
fmt.Printf(" 修改结构体字段:\\n")
// 需要使用指针才能修改
v = reflect.ValueOf(&person)
if v.Kind() == reflect.Ptr {
v = v.Elem() // 获取指针指向的值
nameField = v.FieldByName("Name")
if nameField.CanSet() {
nameField.SetString("Bob")
fmt.Printf(" 修改后的Name: %s\\n", person.Name)
}
ageField := v.FieldByName("Age")
if ageField.CanSet() {
ageField.SetInt(35)
fmt.Printf(" 修改后的Age: %d\\n", person.Age)
}
}
// 嵌套结构体
fmt.Printf(" 嵌套结构体:\\n")
employee := Employee{
Person: Person{Name: "Charlie", Age: 28},
Title: "Developer",
Salary: 80000,
}
t = reflect.TypeOf(employee)
v = reflect.ValueOf(employee)
fmt.Printf(" 嵌套结构体字段数: %d\\n", t.NumField())
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf(" 字段%d: %s (类型: %v)\\n", i, field.Name, field.Type)
// 如果是嵌套结构体,进一步展开
if field.Type.Kind() == reflect.Struct {
fmt.Printf(" 嵌套字段:\\n")
nestedValue := value
nestedType := field.Type
for j := 0; j < nestedType.NumField(); j++ {
nestedField := nestedType.Field(j)
nestedFieldValue := nestedValue.Field(j)
fmt.Printf(" %s: %v\\n", nestedField.Name, nestedFieldValue.Interface())
}
} else {
fmt.Printf(" 值: %v\\n", value.Interface())
}
}
fmt.Println()
}
// demonstrateMethodReflection 演示方法反射
func demonstrateMethodReflection() {
fmt.Println("5. 方法反射:")
// 方法信息
fmt.Printf(" 方法信息:\\n")
person := &Person{Name: "David", Age: 25}
t := reflect.TypeOf(person)
v := reflect.ValueOf(person)
fmt.Printf(" 方法数量: %d\\n", t.NumMethod())
// 遍历方法
for i := 0; i < t.NumMethod(); i++ {
method := t.Method(i)
fmt.Printf(" 方法%d: %s (类型: %v)\\n", i, method.Name, method.Type)
}
// 调用方法
fmt.Printf(" 调用方法:\\n")
// 按名称获取方法
greetMethod := v.MethodByName("Greet")
if greetMethod.IsValid() {
// 调用无参数方法
result := greetMethod.Call(nil)
if len(result) > 0 {
fmt.Printf(" Greet方法返回: %v\\n", result[0].Interface())
}
}
// 调用带参数的方法
setAgeMethod := v.MethodByName("SetAge")
if setAgeMethod.IsValid() {
args := []reflect.Value{reflect.ValueOf(30)}
setAgeMethod.Call(args)
fmt.Printf(" 调用SetAge后年龄: %d\\n", person.Age)
}
// 调用带返回值的方法
getInfoMethod := v.MethodByName("GetInfo")
if getInfoMethod.IsValid() {
result := getInfoMethod.Call(nil)
if len(result) > 0 {
fmt.Printf(" GetInfo方法返回: %v\\n", result[0].Interface())
}
}
// 函数值的反射调用
fmt.Printf(" 函数值的反射调用:\\n")
fn := func(a, b int) int {
return a + b
}
fnValue := reflect.ValueOf(fn)
args := []reflect.Value{
reflect.ValueOf(10),
reflect.ValueOf(20),
}
result := fnValue.Call(args)
fmt.Printf(" 函数调用结果: %v\\n", result[0].Interface())
// 方法集的检查
fmt.Printf(" 方法集的检查:\\n")
// 检查类型是否实现了某个接口
stringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
personType := reflect.TypeOf(person)
fmt.Printf(" Person是否实现Stringer接口: %t\\n",
personType.Implements(stringerType))
fmt.Println()
}
// demonstratePracticalApplications 演示反射的实际应用
func demonstratePracticalApplications() {
fmt.Println("6. 反射的实际应用:")
// 应用1: JSON 序列化
fmt.Printf(" 应用1 - JSON 序列化:\\n")
person := Person{
Name: "Eve",
Age: 32,
Email: "eve@example.com",
}
jsonStr := structToJSON(person)
fmt.Printf(" JSON序列化结果: %s\\n", jsonStr)
// 应用2: 结构体复制
fmt.Printf(" 应用2 - 结构体复制:\\n")
original := Person{Name: "Frank", Age: 40}
copied := copyStruct(original).(Person)
fmt.Printf(" 原始结构体: %+v\\n", original)
fmt.Printf(" 复制结构体: %+v\\n", copied)
// 应用3: 结构体比较
fmt.Printf(" 应用3 - 结构体比较:\\n")
person1 := Person{Name: "Grace", Age: 28}
person2 := Person{Name: "Grace", Age: 28}
person3 := Person{Name: "Henry", Age: 30}
fmt.Printf(" person1 == person2: %t\\n", deepEqual(person1, person2))
fmt.Printf(" person1 == person3: %t\\n", deepEqual(person1, person3))
// 应用4: 配置映射
fmt.Printf(" 应用4 - 配置映射:\\n")
config := map[string]interface{}{
"Name": "Iris",
"Age": 26,
"Email": "iris@example.com",
}
var configPerson Person
mapToStruct(config, &configPerson)
fmt.Printf(" 配置映射结果: %+v\\n", configPerson)
// 应用5: 验证器
fmt.Printf(" 应用5 - 验证器:\\n")
validPerson := Person{Name: "Jack", Age: 25, Email: "jack@example.com"}
invalidPerson := Person{Name: "", Age: -5, Email: "invalid"}
fmt.Printf(" 有效Person验证: %t\\n", validateStruct(validPerson))
fmt.Printf(" 无效Person验证: %t\\n", validateStruct(invalidPerson))
// 应用6: ORM 映射
fmt.Printf(" 应用6 - ORM 映射:\\n")
tableName := getTableName(Person{})
columns := getColumns(Person{})
fmt.Printf(" 表名: %s\\n", tableName)
fmt.Printf(" 列名: %v\\n", columns)
fmt.Println()
}
// demonstrateBestPractices 演示反射的最佳实践
func demonstrateBestPractices() {
fmt.Println("7. 反射的最佳实践:")
// 最佳实践原则
fmt.Printf(" 最佳实践原则:\\n")
fmt.Printf(" 1. 谨慎使用反射,优先考虑类型安全的方案\\n")
fmt.Printf(" 2. 缓存反射结果以提高性能\\n")
fmt.Printf(" 3. 进行充分的错误检查\\n")
fmt.Printf(" 4. 避免在热点路径使用反射\\n")
fmt.Printf(" 5. 使用接口而不是反射来实现多态\\n")
// 性能考虑
fmt.Printf(" 性能考虑:\\n")
// 性能测试示例
person := Person{Name: "Test", Age: 30}
// 直接访问 vs 反射访问
start := time.Now()
for i := 0; i < 100000; i++ {
_ = person.Name // 直接访问
}
directTime := time.Since(start)
start = time.Now()
v := reflect.ValueOf(person)
nameField := v.FieldByName("Name")
for i := 0; i < 100000; i++ {
_ = nameField.Interface() // 反射访问
}
reflectTime := time.Since(start)
fmt.Printf(" 直接访问耗时: %v\\n", directTime)
fmt.Printf(" 反射访问耗时: %v\\n", reflectTime)
fmt.Printf(" 性能差异: %.2fx\\n", float64(reflectTime)/float64(directTime))
// 错误处理
fmt.Printf(" 错误处理:\\n")
// 安全的反射操作
safeReflectOperation := func(obj interface{}, fieldName string) (interface{}, error) {
v := reflect.ValueOf(obj)
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("对象不是结构体")
}
field := v.FieldByName(fieldName)
if !field.IsValid() {
return nil, fmt.Errorf("字段 %s 不存在", fieldName)
}
return field.Interface(), nil
}
// 测试安全操作
result, err := safeReflectOperation(person, "Name")
if err != nil {
fmt.Printf(" 错误: %v\\n", err)
} else {
fmt.Printf(" 安全获取Name字段: %v\\n", result)
}
result, err = safeReflectOperation(person, "NonExistent")
if err != nil {
fmt.Printf(" 预期错误: %v\\n", err)
}
// 反射的替代方案
fmt.Printf(" 反射的替代方案:\\n")
fmt.Printf(" 1. 接口: 使用接口实现多态\\n")
fmt.Printf(" 2. 类型断言: 处理已知的有限类型集合\\n")
fmt.Printf(" 3. 代码生成: 编译时生成类型安全的代码\\n")
fmt.Printf(" 4. 泛型: Go 1.18+ 支持泛型编程\\n")
// 何时使用反射
fmt.Printf(" 何时使用反射:\\n")
fmt.Printf(" ✓ 序列化/反序列化库\\n")
fmt.Printf(" ✓ ORM 框架\\n")
fmt.Printf(" ✓ 配置映射\\n")
fmt.Printf(" ✓ 测试框架\\n")
fmt.Printf(" ✓ 依赖注入容器\\n")
fmt.Printf("\\n")
fmt.Printf(" ✗ 简单的类型转换\\n")
fmt.Printf(" ✗ 已知类型的操作\\n")
fmt.Printf(" ✗ 性能敏感的代码\\n")
fmt.Printf(" ✗ 可以用接口解决的问题\\n")
fmt.Println()
}
// ========== 类型定义 ==========
// Person 人员结构体
type Person struct {
Name string `json:"name" db:"name" validate:"required"`
Age int `json:"age" db:"age" validate:"min=0,max=150"`
Email string `json:"email" db:"email" validate:"email"`
}
// Greet 问候方法
func (p *Person) Greet() string {
return fmt.Sprintf("Hello, I'm %s", p.Name)
}
// SetAge 设置年龄
func (p *Person) SetAge(age int) {
p.Age = age
}
// GetInfo 获取信息
func (p *Person) GetInfo() string {
return fmt.Sprintf("Name: %s, Age: %d, Email: %s", p.Name, p.Age, p.Email)
}
// String 实现 Stringer 接口
func (p Person) String() string {
return fmt.Sprintf("Person{Name: %s, Age: %d}", p.Name, p.Age)
}
// Employee 员工结构体
type Employee struct {
Person
Title string `json:"title" db:"title"`
Salary float64 `json:"salary" db:"salary"`
}
// ========== 辅助函数 ==========
// structToJSON 将结构体转换为 JSON 字符串
func structToJSON(obj interface{}) string {
v := reflect.ValueOf(obj)
t := reflect.TypeOf(obj)
if v.Kind() != reflect.Struct {
return "{}"
}
var parts []string
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
// 获取 JSON 标签
jsonTag := field.Tag.Get("json")
if jsonTag == "" {
jsonTag = strings.ToLower(field.Name)
}
// 根据类型格式化值
var valueStr string
switch value.Kind() {
case reflect.String:
valueStr = fmt.Sprintf("\\\"%s\\\"", value.String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
valueStr = fmt.Sprintf("%d", value.Int())
case reflect.Float32, reflect.Float64:
valueStr = fmt.Sprintf("%.2f", value.Float())
case reflect.Bool:
valueStr = fmt.Sprintf("%t", value.Bool())
default:
valueStr = fmt.Sprintf("\\\"%v\\\"", value.Interface())
}
parts = append(parts, fmt.Sprintf("\\\"%s\\\": %s", jsonTag, valueStr))
}
return "{" + strings.Join(parts, ", ") + "}"
}
// copyStruct 复制结构体
func copyStruct(src interface{}) interface{} {
srcValue := reflect.ValueOf(src)
srcType := reflect.TypeOf(src)
if srcValue.Kind() != reflect.Struct {
return src
}
// 创建新的结构体实例
newValue := reflect.New(srcType).Elem()
// 复制所有字段
for i := 0; i < srcValue.NumField(); i++ {
srcField := srcValue.Field(i)
newField := newValue.Field(i)
if newField.CanSet() {
newField.Set(srcField)
}
}
return newValue.Interface()
}
// deepEqual 深度比较两个值
func deepEqual(a, b interface{}) bool {
va := reflect.ValueOf(a)
vb := reflect.ValueOf(b)
if va.Type() != vb.Type() {
return false
}
switch va.Kind() {
case reflect.Struct:
for i := 0; i < va.NumField(); i++ {
if !deepEqual(va.Field(i).Interface(), vb.Field(i).Interface()) {
return false
}
}
return true
case reflect.Slice:
if va.Len() != vb.Len() {
return false
}
for i := 0; i < va.Len(); i++ {
if !deepEqual(va.Index(i).Interface(), vb.Index(i).Interface()) {
return false
}
}
return true
case reflect.Map:
if va.Len() != vb.Len() {
return false
}
for _, key := range va.MapKeys() {
aVal := va.MapIndex(key)
bVal := vb.MapIndex(key)
if !bVal.IsValid() || !deepEqual(aVal.Interface(), bVal.Interface()) {
return false
}
}
return true
default:
return va.Interface() == vb.Interface()
}
}
// mapToStruct 将 map 映射到结构体
func mapToStruct(m map[string]interface{}, dst interface{}) error {
dstValue := reflect.ValueOf(dst)
if dstValue.Kind() != reflect.Ptr || dstValue.Elem().Kind() != reflect.Struct {
return fmt.Errorf("dst 必须是结构体指针")
}
dstValue = dstValue.Elem()
dstType := dstValue.Type()
for i := 0; i < dstValue.NumField(); i++ {
field := dstType.Field(i)
fieldValue := dstValue.Field(i)
if !fieldValue.CanSet() {
continue
}
// 从 map 中获取对应的值
if mapValue, ok := m[field.Name]; ok {
mapValueReflect := reflect.ValueOf(mapValue)
// 类型转换
if mapValueReflect.Type().ConvertibleTo(fieldValue.Type()) {
fieldValue.Set(mapValueReflect.Convert(fieldValue.Type()))
}
}
}
return nil
}
// validateStruct 验证结构体
func validateStruct(obj interface{}) bool {
v := reflect.ValueOf(obj)
t := reflect.TypeOf(obj)
if v.Kind() != reflect.Struct {
return false
}
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
// 获取验证标签
validateTag := field.Tag.Get("validate")
if validateTag == "" {
continue
}
// 解析验证规则
rules := strings.Split(validateTag, ",")
for _, rule := range rules {
if !validateField(value, strings.TrimSpace(rule)) {
return false
}
}
}
return true
}
// validateField 验证单个字段
func validateField(value reflect.Value, rule string) bool {
switch rule {
case "required":
return !value.IsZero()
case "email":
if value.Kind() == reflect.String {
email := value.String()
return strings.Contains(email, "@") && strings.Contains(email, ".")
}
return false
default:
// 处理 min=0, max=150 等规则
if strings.HasPrefix(rule, "min=") {
minStr := strings.TrimPrefix(rule, "min=")
if min, err := strconv.Atoi(minStr); err == nil {
if value.Kind() == reflect.Int {
return value.Int() >= int64(min)
}
}
}
if strings.HasPrefix(rule, "max=") {
maxStr := strings.TrimPrefix(rule, "max=")
if max, err := strconv.Atoi(maxStr); err == nil {
if value.Kind() == reflect.Int {
return value.Int() <= int64(max)
}
}
}
}
return true
}
// getTableName 获取表名
func getTableName(obj interface{}) string {
t := reflect.TypeOf(obj)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
// 将结构体名转换为表名(简单的复数形式)
name := t.Name()
return strings.ToLower(name) + "s"
}
// getColumns 获取列名
func getColumns(obj interface{}) []string {
t := reflect.TypeOf(obj)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
var columns []string
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// 获取数据库标签
dbTag := field.Tag.Get("db")
if dbTag != "" {
columns = append(columns, dbTag)
} else {
columns = append(columns, strings.ToLower(field.Name))
}
}
return columns
}
/*
运行这个程序:
go run 01-reflection.go
学习要点:
1. 反射是程序在运行时检查自身结构的能力
2. Go 通过 reflect 包提供反射功能
3. 反射主要包括类型反射和值反射
4. 反射可以用于序列化、ORM、配置映射等场景
5. 反射有性能开销,应该谨慎使用
反射的核心概念:
1. reflect.Type: 表示类型信息
2. reflect.Value: 表示值信息
3. reflect.Kind: 表示基础类型种类
4. 反射遵循 Go 的类型系统规则
5. 反射可以检查和修改值
类型反射:
1. 获取类型信息reflect.TypeOf()
2. 类型名称和种类Name(), Kind()
3. 复合类型Elem(), Key(), In(), Out()
4. 结构体字段NumField(), Field()
5. 方法信息NumMethod(), Method()
值反射:
1. 获取值信息reflect.ValueOf()
2. 值的访问Interface(), Int(), String()
3. 值的修改Set(), SetInt(), SetString()
4. 集合操作Len(), Index(), MapIndex()
5. 创建新值New(), MakeSlice(), MakeMap()
结构体反射:
1. 字段访问Field(), FieldByName()
2. 字段信息Name, Type, Tag
3. 字段修改CanSet(), Set()
4. 标签解析Tag.Get()
5. 嵌套结构体处理
方法反射:
1. 方法信息Method(), MethodByName()
2. 方法调用Call()
3. 方法类型Type, NumIn(), NumOut()
4. 接口检查Implements()
5. 方法集分析
实际应用场景:
1. JSON 序列化/反序列化
2. ORM 数据库映射
3. 配置文件映射
4. 结构体验证
5. 依赖注入
6. 测试框架
7. 代码生成工具
性能考虑:
1. 反射比直接访问慢很多
2. 缓存反射结果可以提高性能
3. 避免在热点路径使用反射
4. 考虑使用接口替代反射
5. 编译时代码生成是更好的选择
最佳实践:
1. 谨慎使用反射,优先考虑类型安全
2. 进行充分的错误检查
3. 缓存反射操作的结果
4. 使用接口实现多态
5. 考虑性能影响
6. 提供清晰的文档说明
注意事项:
1. 反射会破坏类型安全
2. 反射代码难以理解和维护
3. 反射错误只能在运行时发现
4. 反射会影响代码的可读性
5. 反射操作可能导致 panic
*/