泛型结构体
概念说明
泛型结构体就是把结构体里“会变化的字段类型”抽成类型参数。
使用时再指定具体类型,例如 Result[User]、Result[[]int]。
它适合这种场景:
- 结构体的大部分字段都一样
- 只有某个字段的类型会变化
先看一个实际场景
假设我们在写接口返回值,很多接口都会返回这三部分:
- 状态码
Code - 提示信息
Message - 具体数据
Data
如果不用泛型,通常会写成:
| |
这里能看到:
Code和Message是重复的- 真正变化的只有
Data的类型
这时就可以把 Data 抽成类型参数,变成一个泛型结构体。
泛型结构体示例
| |
输出结果:
| |
这段代码怎么理解
1. 看结构体定义
| |
Result是结构体名。[T any]表示声明一个类型参数T。any表示这里先不限制T的具体类型。Data T表示Data的类型由T决定。
也就是说:
Result[User]时,Data就是UserResult[[]int]时,Data就是[]int
2. 看方法写法
| |
- 方法接收者要写成
Result[T],不能只写Result。 - 返回值类型写成
T,表示返回具体实例里的Data类型。 - 所以
userResult.GetData()返回User,idsResult.GetData()返回[]int。
3. 看实例化
| |
这两句的意思是:
Result[User]把T替换成UserResult[[]int]把T替换成[]int
替换后,类型就是确定的:
userResult.Data的类型是UseridsResult.Data的类型是[]int
4. 为什么这里不是 any
如果把 Data 写成 any,虽然也能存不同类型的数据,
但取出来时类型信息不明确,使用时会麻烦很多。
泛型结构体不是“统一存成模糊类型”,
而是“同一个结构模板,在使用时变成明确类型”。
所以这句代码才可以直接写:
| |
因为 GetData() 返回的是 User,不是模糊的 any。
这个例子里,泛型结构体带来的效果
不用泛型时,可能要写:
| |
用了泛型后,只保留一份结构定义:
| |
使用时再写成:
| |
这样做的好处是:
- 结构定义更统一
- 重复代码更少
- 字段类型仍然明确
语法/规则
- 泛型结构体写法是
type Name[T Constraint] struct { ... }。 - 字段类型可以直接使用类型参数
T。 - 使用时要写具体类型,例如
Result[User]。 - 给泛型结构体定义方法时,接收者也要带上
[T]。
常见错误
- 使用时忘记指定具体类型。
- 给泛型结构体写方法时,接收者忘记带
[T]。 - 把本来应该写成
T的字段写成了any,丢掉了类型安全。