章节

16.7 反射实现简单映射

本篇通过一个简化映射示例理解反射在 ORM 场景中的基本作用。

反射实现简单映射

概念说明

ORM 常需要把结构体字段映射成数据库字段。
反射可以在运行时读取结构体字段名和 tag,从而生成通用映射逻辑。

下面示例只是帮助理解思想。
真实 ORM 还会处理 SQL 构造、类型转换、关联关系、事务等大量细节。

语法/规则

  1. 使用结构体 tag 描述字段映射名。
  2. 通过 reflect.TypeOf 读取字段元信息。
  3. 通过 reflect.ValueOf 读取字段值。
  4. 遍历字段时跳过未导出或无效字段。
  5. 简化示例只适合理解反射思想,不应直接当作生产 ORM 使用。

简单映射示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Name string `db:"name"`
	Age  int    `db:"age"`
}

func ToMap(value any) map[string]any {
	result := make(map[string]any)
	typ := reflect.TypeOf(value)
	val := reflect.ValueOf(value)

	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)
		key := field.Tag.Get("db") // 优先使用 db tag 作为映射键
		if key == "" {
			key = field.Name
		}
		result[key] = val.Field(i).Interface()
	}

	return result
}

func main() {
	user := User{Name: "abin", Age: 21}
	fmt.Println(ToMap(user))
}

输出结果:

1
map[age:21 name:abin]

常见错误

  1. 把学习示例直接当作完整 ORM 使用,忽略类型转换和 SQL 安全问题。
  2. 没有处理指针结构体,传入 &User{} 时会因为 Kind 不匹配出错。
  3. 读取未导出字段的值,可能触发 panic。
  4. 以为 tag 会自动生成映射,实际必须由代码读取并处理。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字