Go高级教程:反射 (Reflection) 实战

大家好,我是极客老墨。 反射 (Reflection) 赋予了程序在运行时检查和修改自身状态的能力。从 JSON 解析到 ORM 框架(如 GORM),再到依赖注入,它们的底层都离不开反射。有人说"反射是魔鬼",也有人说"没有反射,就没有现代 Web 框架"。这篇就带你拆解 reflect 包,学会如何在运行时动态操作对象。 1. 核心概念:Type 和 Value 在 reflect 包中,有两位绝对主角: reflect.Type:这是啥?(类型信息,如 int, string, User) reflect.Value:这值多少?(具体的数据,如 42, “hello”, User{Name:“Hank”}) 一切反射操作的起点都是 interface{}。 1package main 2 3import ( 4 "fmt" 5 "reflect" 6) 7 8func main() { 9 x := 3.14 10 11 // 1. 获取类型 12 t := reflect.TypeOf(x) 13 fmt.Println("Type:", t) // float64 14 15 // 2. 获取值 16 v := reflect.ValueOf(x) 17 fmt.Println("Value:", v) // 3.14 18} graph LR subgraph iface ["interface{}"] direction TB TypePtr["_type pointer"] DataPtr["data pointer"] end TypePtr -->|"reflect.TypeOf"| RType["reflect.Type"] DataPtr -->|"reflect.ValueOf"| RValue["reflect.Value"] style iface fill:#f9f9f9,stroke:#333,stroke-width:2px,color:#333 style TypePtr fill:#e1f5fe,stroke:#01579b,color:#01579b style DataPtr fill:#e1f5fe,stroke:#01579b,color:#01579b style RType fill:#fff9c4,stroke:#fbc02d,color:#333 style RValue fill:#fff9c4,stroke:#fbc02d,color:#333 2. 三大反射定律 Go 的反射有三条铁律(出自 Rob Pike): ...

2026-01-28 · 3 min · 485 words · 老墨

[GoLang避坑实战-09] 接口即正义:解密 Go 语言"鸭子类型"的实战精髓

大家好,我是极客老墨。 Go 没有类,也没有继承。它用结构体封装数据,用接口定义行为。这种"组合优于继承"的设计,让代码更灵活、更解耦。 这篇就聊聊 Go 的结构体和接口,看看它们是怎么配合工作的。 结构体基础 结构体是一组字段的集合,用来封装相关的数据。 定义和初始化 1// 定义结构体 2type Person struct { 3 Name string 4 Age int 5} 6 7// 初始化方式 1:按字段顺序 8p1 := Person{"Alice", 30} 9 10// 初始化方式 2:指定字段名(推荐) 11p2 := Person{ 12 Name: "Bob", 13 Age: 25, 14} 15 16// 初始化方式 3:部分字段(其余为零值) 17p3 := Person{Name: "Charlie"} // Age 为 0 18 19// 初始化方式 4:使用 new(返回指针) 20p4 := new(Person) 21p4.Name = "David" 要点: 字段名首字母大写表示导出(public),小写表示私有(package 内可见) 推荐使用字段名初始化,代码更清晰 未初始化的字段会被赋予零值 访问和修改字段 1p := Person{Name: "Alice", Age: 30} 2 3// 访问字段 4fmt.Println(p.Name) // Alice 5 6// 修改字段 7p.Age = 31 8 9// 指针访问(Go 会自动解引用) 10ptr := &p 11ptr.Name = "Alicia" // 等价于 (*ptr).Name = "Alicia" 匿名字段 结构体可以包含匿名字段(只有类型,没有字段名)。 ...

2024-09-15 · 9 min · 1710 words · 老墨