This commit is contained in:
2025-08-24 13:01:09 +08:00
parent 61e51ad014
commit f028913eb8
36 changed files with 10420 additions and 70 deletions

View File

@@ -0,0 +1,967 @@
/*
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
*/