章节

13.2 泛型结构体

本篇通过接口返回值场景,对比重复结构体与 Result[T] 的写法,学习泛型结构体的定义、实例化与方法写法。

泛型结构体

概念说明

泛型结构体就是把结构体里“会变化的字段类型”抽成类型参数。
使用时再指定具体类型,例如 Result[User]Result[[]int]

它适合这种场景:

  1. 结构体的大部分字段都一样
  2. 只有某个字段的类型会变化

先看一个实际场景

假设我们在写接口返回值,很多接口都会返回这三部分:

  1. 状态码 Code
  2. 提示信息 Message
  3. 具体数据 Data

如果不用泛型,通常会写成:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
type User struct {
	Name string
	Age  int
}

type UserResult struct {
	Code    int
	Message string
	Data    User
}

type IntListResult struct {
	Code    int
	Message string
	Data    []int
}

这里能看到:

  1. CodeMessage 是重复的
  2. 真正变化的只有 Data 的类型

这时就可以把 Data 抽成类型参数,变成一个泛型结构体。

泛型结构体示例

 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
34
35
36
37
38
package main

import "fmt"

type Result[T any] struct {
	Code    int
	Message string
	Data    T
}

func (r Result[T]) GetData() T {
	return r.Data
}

type User struct {
	Name string
	Age  int
}

func main() {
	userResult := Result[User]{
		Code:    200,
		Message: "success",
		Data: User{
			Name: "Tom",
			Age:  20,
		},
	}

	idsResult := Result[[]int]{
		Code:    200,
		Message: "success",
		Data:    []int{101, 102, 103},
	}

	fmt.Println(userResult.GetData().Name)
	fmt.Println(idsResult.GetData())
}

输出结果:

1
2
Tom
[101 102 103]

这段代码怎么理解

1. 看结构体定义

1
2
3
4
5
type Result[T any] struct {
	Code    int
	Message string
	Data    T
}
  1. Result 是结构体名。
  2. [T any] 表示声明一个类型参数 T
  3. any 表示这里先不限制 T 的具体类型。
  4. Data T 表示 Data 的类型由 T 决定。

也就是说:

  1. Result[User] 时,Data 就是 User
  2. Result[[]int] 时,Data 就是 []int

2. 看方法写法

1
2
3
func (r Result[T]) GetData() T {
	return r.Data
}
  1. 方法接收者要写成 Result[T],不能只写 Result
  2. 返回值类型写成 T,表示返回具体实例里的 Data 类型。
  3. 所以 userResult.GetData() 返回 UseridsResult.GetData() 返回 []int

3. 看实例化

1
2
userResult := Result[User]{ ... }
idsResult := Result[[]int]{ ... }

这两句的意思是:

  1. Result[User]T 替换成 User
  2. Result[[]int]T 替换成 []int

替换后,类型就是确定的:

  1. userResult.Data 的类型是 User
  2. idsResult.Data 的类型是 []int

4. 为什么这里不是 any

如果把 Data 写成 any,虽然也能存不同类型的数据,
但取出来时类型信息不明确,使用时会麻烦很多。

泛型结构体不是“统一存成模糊类型”,
而是“同一个结构模板,在使用时变成明确类型”。

所以这句代码才可以直接写:

1
fmt.Println(userResult.GetData().Name)

因为 GetData() 返回的是 User,不是模糊的 any

这个例子里,泛型结构体带来的效果

不用泛型时,可能要写:

1
2
3
4
type UserResult struct { ... }
type ProductResult struct { ... }
type OrderResult struct { ... }
type IntListResult struct { ... }

用了泛型后,只保留一份结构定义:

1
type Result[T any] struct { ... }

使用时再写成:

1
2
3
4
Result[User]
Result[Product]
Result[Order]
Result[[]int]

这样做的好处是:

  1. 结构定义更统一
  2. 重复代码更少
  3. 字段类型仍然明确

语法/规则

  1. 泛型结构体写法是 type Name[T Constraint] struct { ... }
  2. 字段类型可以直接使用类型参数 T
  3. 使用时要写具体类型,例如 Result[User]
  4. 给泛型结构体定义方法时,接收者也要带上 [T]

常见错误

  1. 使用时忘记指定具体类型。
  2. 给泛型结构体写方法时,接收者忘记带 [T]
  3. 把本来应该写成 T 的字段写成了 any,丢掉了类型安全。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字