# 4.4.4-11 泛型类型

&#x20;函数与类型中申明的泛型使用如下数据结构来表示：

```go
type TypeParam struct {
    check *Checker  // for lazy type bound completion
    id    uint64    // unique id
    obj   *TypeName // 
    index int       // parameter index
    bound Type      // *Named or *Interface; underlying type is always *Interface
}
```

&#x20;除此之外还有三个类型用于泛型，其定义如下：

```go
type instance struct {
    check   *Checker     // for lazy instantiation
    pos     syntax.Pos   // position of type instantiation; for error reporting only
    base    *Named       // parameterized type to be instantiated
    targs   []Type       // type arguments
    poslist []syntax.Pos // position of each targ; for error reporting only
    value   Type         // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set
}
type bottom struct{}
type top struct{}
```

`bottom` 与 `top` 是两个标记类型。当接口中包含泛型的 constraints 时，我们需要推算出当前接口中 constraints 所包含的实际类型，例如如下申明：

```go
type SmallInt interface {
    type int8, int16, int32
}

type BigInt interface {
    type int, int32, int64
}

type MediumInt interface {
    SmallInt
    BigInt
    type int16, int32
}
```

`MediumInt` 中除了申明了自己的 constraints 列表, 还内嵌了 `SmallInt` 与 `BigInt`, 此时 `MediumInt` 的实际 constraints 自然应该是三者的并集：int32. `bottom` 与 `top` 两个类型用于表示两个特殊的集合：前者表示空集，后者表示全集。

instance 代表一个实例化了的泛型，泛型也叫类型参数（type parameter），我们先来回顾一下普通的函数参数：

```go
func sum(i, j int) int {
    return i + j
}
```

但凡说道“参数”，就需要使用者将具体的实参传递进去。i, j 是函数 sum 的形参，我们可以将函数看着是一个计算模版，当调用者提供该模版的实参时，我们就可以通过该“模版”计算出最终值。那么“类型参数”该如何传递呢？我们先来看一个典型的泛型定义：

```go
type Node[T comparable] struct {
    val T
}
```

Node 是我们定义的一个类型，但是该类型并不完备：属性 val 的类型 T 还是未知的，由使用者提供。我们可以将 T 看着是 Node 的类型参数，从而将将 `Node[T comparable]` 看着是一个类型模版，当使用者提供具体的参数类型时，我们就可以得到一个具体的Node类型。例如当 T 为 int32 时，我们得到具体类型是：

```go
type Node struct {
    val int32
}
```

该过程叫着类型的实例化。所以在代码中，任何使用泛型 Node 的地方都需要传入类型参数，例如如下代码：

```go
// 该方法中一共有三个实例化的 Node 类型：Node[string], Node[float32] 与 Node[int32]
func convert(nod Node[string]) Node[float32] {   
var _ Node[int32]
}
```

go 编译器内部使用 `instance` 来表示一个实例化的泛型类型，其中 `base` 是“类型模版”，而 `targs` 就是具体传入的参数类型值。例如上述代码中将会生成三个具体类型，对应三个 instance 实例。

事实上，编译器在[生成 IR Tree](/golang-bian-yi-qi-ir-tree/untitled-2.md#org3e1ddf1) 时便会为所有泛型函数做实例化。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gocompiler.shizhz.me/golang-bian-yi-qi-lei-xing-jian-cha/4.4.411-fan-xing-lei-xing-fl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
