Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

go/types - Go 类型系统

go/types 包提供了 Go 语言的类型检查和类型信息访问功能,是 Go 静态分析工具的核心组件。

概述

go/types 包用于对 Go 代码进行类型检查,提供类型推断、类型验证和类型信息访问功能,是构建编译器、lint 工具和 IDE 的基础。

包导入

import (
    "go/types"
    "go/ast"
    "go/importer"
    "fmt"
)

基本使用

// 1. 创建类型检查配置
conf := types.Config{
    Importer: importer.Default(),
}

// 2. 类型检查
info := &types.Info{
    Types: make(map[ast.Expr]types.TypeAndValue),
    Defs:  make(map[*ast.Ident]types.Object),
    Uses:  make(map[*ast.Ident]types.Object),
}

// 3. 检查包
pkg, err := conf.Check("mypackage", fset, files, info)
if err != nil {
    panic(err)
}

// 4. 访问类型信息
for expr, tv := range info.Types {
    fmt.Printf("%T: %s\n", expr, tv.Type)
}

典型示例

示例 1:类型检查简单代码

package main

import (
    "fmt"
    "go/ast"
    "go/importer"
    "go/parser"
    "go/token"
    "go/types"
)

func main() {
    src := `
package main

import "fmt"

func Add(a, b int) int {
    return a + b
}

func main() {
    x := Add(1, 2)
    fmt.Println(x)
}
`

    // 解析源码
    fset := token.NewFileSet()
    file, _ := parser.ParseFile(fset, "add.go", src, parser.ParseComments)

    // 类型检查
    conf := types.Config{
        Importer: importer.Default(),
    }
    
    info := &types.Info{
        Types: make(map[ast.Expr]types.TypeAndValue),
        Defs:  make(map[*ast.Ident]types.Object),
        Uses:  make(map[*ast.Ident]types.Object),
    }
    
    pkg, err := conf.Check("main", fset, []*ast.File{file}, info)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("包名:%s\n", pkg.Name())
    fmt.Printf("作用域对象:%d\n", len(pkg.Scope().Names()))
    
    // 打印类型信息
    for expr, tv := range info.Types {
        if ident, ok := expr.(*ast.Ident); ok {
            fmt.Printf("%s: %s\n", ident.Name, tv.Type)
        }
    }
}

运行

$ go run main.go
包名:main
作用域对象:3
Add: func(a int, b int) int
x: int
fmt: "fmt"
println: func(x ...int)

示例 2:获取对象信息

package main

import (
    "fmt"
    "go/ast"
    "go/importer"
    "go/parser"
    "go/token"
    "go/types"
)

func main() {
    src := `
package main

var GlobalVar int

type Person struct {
    Name string
    Age  int
}

func (p *Person) SayHello() {
    println("Hello")
}
`

    fset := token.NewFileSet()
    file, _ := parser.ParseFile(fset, "test.go", src, parser.ParseComments)
    
    conf := types.Config{
        Importer: importer.Default(),
    }
    
    info := &types.Info{
        Defs: make(map[*ast.Ident]types.Object),
    }
    
    pkg, _ := conf.Check("main", fset, []*ast.File{file}, info)
    
    // 遍历定义
    for ident, obj := range info.Defs {
        if obj != nil {
            fmt.Printf("%s: %s (%T)\n", 
                ident.Name, 
                obj.Type(),
                obj)
        }
    }
}

运行

$ go run main.go
GlobalVar: int (*types.Var)
Person: struct{Name string; Age int} (*types.TypeName)
p: *Person (*types.Var)
SayHello: func() (*types.Func)

一、Type 接口

Type 接口定义

Type

定义

type Type interface {
    Underlying() Type
    String() string
}

说明

  • 所有类型都必须实现此接口
  • Underlying():返回底层类型
  • String():返回类型字符串表示

Basic 类型

Basic

定义

type Basic struct {
    // 内部字段
}

说明

  • 表示基本类型(int, string, bool 等)
  • 最常用的类型之一

方法

  • Underlying() Type
  • String() string
  • Kind() BasicKind
  • Info() BasicInfo
  • Name() string

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 获取基本类型
    typesInfo := []*types.Basic{
        types.Typ[types.Int],
        types.Typ[types.String],
        types.Typ[types.Bool],
        types.Typ[types.Float64],
    }
    
    for _, t := range typesInfo {
        fmt.Printf("%-10s Kind: %v Info: %v\n",
            t.String(), t.Kind(), t.Info())
    }
}

Array 类型

Array

定义

type Array struct {
    // 内部字段
}

说明

  • 表示数组类型
  • 包含长度和元素类型

方法

  • Underlying() Type
  • String() string
  • Elem() Type
  • Len() int64

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建数组类型 [10]int
    elemType := types.Typ[types.Int]
    arrayType := types.NewArray(elemType, 10)
    
    fmt.Printf("类型:%s\n", arrayType.String())
    fmt.Printf("元素类型:%s\n", arrayType.Elem())
    fmt.Printf("长度:%d\n", arrayType.Len())
}

运行

$ go run main.go
类型:[10]int
元素类型:int
长度:10

Slice 类型

Slice

定义

type Slice struct {
    // 内部字段
}

说明

  • 表示切片类型
  • 由元素类型构造

方法

  • Underlying() Type
  • String() string
  • Elem() Type

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建切片类型 []string
    elemType := types.Typ[types.String]
    sliceType := types.NewSlice(elemType)
    
    fmt.Printf("类型:%s\n", sliceType.String())
    fmt.Printf("元素类型:%s\n", sliceType.Elem())
}

运行

$ go run main.go
类型:[]string
元素类型:string

Map 类型

Map

定义

type Map struct {
    // 内部字段
}

说明

  • 表示 Map 类型
  • 包含键类型和值类型

方法

  • Underlying() Type
  • String() string
  • Key() Type
  • Elem() Type
  • IsComparable() bool

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建 Map 类型 map[string]int
    keyType := types.Typ[types.String]
    valueType := types.Typ[types.Int]
    mapType := types.NewMap(keyType, valueType)
    
    fmt.Printf("类型:%s\n", mapType.String())
    fmt.Printf("键类型:%s\n", mapType.Key())
    fmt.Printf("值类型:%s\n", mapType.Elem())
    fmt.Printf("可比较:%v\n", mapType.IsComparable())
}

运行

$ go run main.go
类型:map[string]int
键类型:string
值类型:int
可比较:false

Struct 类型

Struct

定义

type Struct struct {
    // 内部字段
}

说明

  • 表示结构体类型
  • 包含字段列表和标签

方法

  • Underlying() Type
  • String() string
  • NumFields() int
  • Field(i int) *Var
  • Tag(i int) string
  • IsComparable() bool

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建结构体类型
    fields := []*types.Var{
        types.NewField(0, nil, "Name", types.Typ[types.String], false),
        types.NewField(0, nil, "Age", types.Typ[types.Int], false),
    }
    
    tags := []string{`json:"name"`, `json:"age"`}
    
    structType := types.NewStruct(fields, tags)
    
    fmt.Printf("类型:%s\n", structType.String())
    fmt.Printf("字段数:%d\n", structType.NumFields())
    
    for i := 0; i < structType.NumFields(); i++ {
        field := structType.Field(i)
        tag := structType.Tag(i)
        fmt.Printf("  %s %s %s\n", field.Name(), field.Type(), tag)
    }
}

运行

$ go run main.go
类型:struct{Name string; Age int}
字段数:2
  Name string json:"name"
  Age int json:"age"

Pointer 类型

Pointer

定义

type Pointer struct {
    // 内部字段
}

说明

  • 表示指针类型
  • 由基础类型构造

方法

  • Underlying() Type
  • String() string
  • Elem() Type

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建指针类型 *int
    elemType := types.Typ[types.Int]
    ptrType := types.NewPointer(elemType)
    
    fmt.Printf("类型:%s\n", ptrType.String())
    fmt.Printf("指向类型:%s\n", ptrType.Elem())
}

运行

$ go run main.go
类型:*int
指向类型:int

Signature 类型(函数签名)

Signature

定义

type Signature struct {
    // 内部字段
}

说明

  • 表示函数签名
  • 包含参数、返回值和接收者

方法

  • Underlying() Type
  • String() string
  • Params() *Tuple
  • Results() *Tuple
  • Recv() *Var
  • Variadic() bool

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建函数签名 func(int, int) int
    params := types.NewTuple(
        types.NewVar(0, nil, "a", types.Typ[types.Int]),
        types.NewVar(0, nil, "b", types.Typ[types.Int]),
    )
    
    results := types.NewTuple(
        types.NewVar(0, nil, "", types.Typ[types.Int]),
    )
    
    sig := types.NewSignature(nil, params, results, false)
    
    fmt.Printf("签名:%s\n", sig.String())
    fmt.Printf("参数数:%d\n", sig.Params().Len())
    fmt.Printf("返回值数:%d\n", sig.Results().Len())
    fmt.Printf("可变参数:%v\n", sig.Variadic())
}

运行

$ go run main.go
签名:func(a int, b int) int
参数数:2
返回值数:1
可变参数:false

Interface 类型

Interface

定义

type Interface struct {
    // 内部字段
}

说明

  • 表示接口类型
  • 包含方法列表和嵌入接口

方法

  • Underlying() Type
  • String() string
  • NumMethods() int
  • Method(i int) *Func
  • NumEmbeddeds() int
  • Embedded(i int) Type
  • IsComparable() bool

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建接口类型
    methods := []*types.Func{
        types.NewFunc(0, nil, "Read", 
            types.NewSignature(nil, 
                types.NewTuple(types.NewVar(0, nil, "p", types.NewSlice(types.Typ[types.Byte]))),
                types.NewTuple(
                    types.NewVar(0, nil, "n", types.Typ[types.Int]),
                    types.NewVar(0, nil, "err", types.Universe.Lookup("error").Type()),
                ),
                false,
            )),
    }
    
    iface := types.NewInterfaceType(methods, nil)
    
    fmt.Printf("接口:%s\n", iface.String())
    fmt.Printf("方法数:%d\n", iface.NumMethods())
}

Chan 类型

Chan

定义

type Chan struct {
    // 内部字段
}

说明

  • 表示 Channel 类型
  • 包含方向和元素类型

方法

  • Underlying() Type
  • String() string
  • Elem() Type
  • Dir() ChanDir

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建 Channel 类型
    elemType := types.Typ[types.Int]
    
    // 双向 channel
    chanType := types.NewChan(types.SendRecv, elemType)
    fmt.Printf("双向:%s\n", chanType.String())
    
    // 发送 channel
    sendType := types.NewChan(types.SendOnly, elemType)
    fmt.Printf("发送:%s\n", sendType.String())
    
    // 接收 channel
    recvType := types.NewChan(types.RecvOnly, elemType)
    fmt.Printf("接收:%s\n", recvType.String())
}

运行

$ go run main.go
双向:chan int
发送:chan<- int
接收:<-chan int

Tuple 类型

Tuple

定义

type Tuple struct {
    // 内部字段
}

说明

  • 表示元组类型(参数列表、返回值列表)
  • 由变量列表组成

方法

  • Underlying() Type
  • String() string
  • Len() int
  • At(i int) *Var
  • Variables() []*Var

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建元组
    vars := types.NewTuple(
        types.NewVar(0, nil, "x", types.Typ[types.Int]),
        types.NewVar(0, nil, "y", types.Typ[types.String]),
    )
    
    fmt.Printf("元组:%s\n", vars.String())
    fmt.Printf("变量数:%d\n", vars.Len())
    
    for i := 0; i < vars.Len(); i++ {
        v := vars.At(i)
        fmt.Printf("  %s: %s\n", v.Name(), v.Type())
    }
}

运行

$ go run main.go
元组:(x int, y string)
变量数:2
  x: int
  y: string

Named 类型(命名类型)

Named

定义

type Named struct {
    // 内部字段
}

说明

  • 表示命名类型(type MyType int)
  • 包含底层类型和方法

方法

  • Underlying() Type
  • String() string
  • Obj() *TypeName
  • NumMethods() int
  • Method(i int) *Func
  • SetUnderlying(underlying Type)
  • AddMethod(m *Func)

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建命名类型
    typeName := types.NewTypeName(0, nil, "MyInt", nil)
    namedType := types.NewNamed(typeName, types.Typ[types.Int], nil)
    
    fmt.Printf("类型:%s\n", namedType.String())
    fmt.Printf("底层类型:%s\n", namedType.Underlying())
    fmt.Printf("对象:%s\n", namedType.Obj().Name())
}

运行

$ go run main.go
类型:MyInt
底层类型:int
对象:MyInt

二、Object 接口

Object 接口定义

Object

定义

type Object interface {
    Parent() *Scope
    Pos() token.Pos
    Pkg() *Package
    Name() string
    Type() Type
    Exported() bool
    String() string
}

说明

  • 表示命名对象(变量、函数、类型等)
  • 所有对象都必须实现此接口

Package 类型

Package

定义

type Package struct {
    // 内部字段
}

说明

  • 表示 Go 包
  • 包含包名、路径、作用域等信息

方法

  • Name() string
  • Path() string
  • Scope() *Scope
  • Imports() []*Package
  • Complete() bool
  • MarkComplete()
  • SetImports(list []*Package)

示例

package main

import (
    "fmt"
    "go/importer"
    "go/types"
)

func main() {
    // 导入包
    imp := importer.Default()
    pkg, _ := imp.Import("fmt")
    
    fmt.Printf("包名:%s\n", pkg.Name())
    fmt.Printf("路径:%s\n", pkg.Path())
    fmt.Printf("完整:%v\n", pkg.Complete())
    
    // 遍历作用域
    scope := pkg.Scope()
    for _, name := range scope.Names() {
        obj := scope.Lookup(name)
        if obj.Exported() {
            fmt.Printf("  %s: %s\n", name, obj.Type())
        }
    }
}

Scope 类型

Scope

定义

type Scope struct {
    // 内部字段
}

说明

  • 表示作用域
  • 包含对象映射和父子关系

方法

  • Parent() *Scope
  • Child(i int) *Scope
  • NumChildren() int
  • Insert(obj Object) Object
  • Lookup(name string) Object
  • LookupParent(name string, pos token.Pos) (*Scope, Object)
  • Names() []string
  • Contains(pos token.Pos) bool

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建作用域
    outer := types.NewScope(nil, 0, 0, "outer")
    inner := types.NewScope(outer, 0, 0, "inner")
    
    // 插入对象
    x := types.NewVar(0, nil, "x", types.Typ[types.Int])
    outer.Insert(x)
    
    // 查找
    obj := outer.Lookup("x")
    fmt.Printf("找到:%s\n", obj.Name())
    
    // 遍历名称
    fmt.Printf("作用域对象:%v\n", outer.Names())
}

Var 类型(变量)

Var

定义

type Var struct {
    // 内部字段
}

说明

  • 表示变量(字段、参数、返回值、局部变量)
  • 最常用的 Object 之一

方法

  • Parent() *Scope
  • Pos() token.Pos
  • Pkg() *Package
  • Name() string
  • Type() Type
  • Exported() bool
  • String() string
  • IsField() bool
  • Anonymous() bool

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建变量
    x := types.NewVar(0, nil, "x", types.Typ[types.Int])
    field := types.NewField(0, nil, "Name", types.Typ[types.String], false)
    param := types.NewParam(0, nil, "a", types.Typ[types.Int])
    
    fmt.Printf("变量:%s %s (字段:%v)\n", x.Name(), x.Type(), x.IsField())
    fmt.Printf("字段:%s %s (字段:%v)\n", field.Name(), field.Type(), field.IsField())
    fmt.Printf("参数:%s %s\n", param.Name(), param.Type())
}

运行

$ go run main.go
变量:x int (字段:false)
字段:Name string (字段:true)
参数:a int

Func 类型(函数)

Func

定义

type Func struct {
    // 内部字段
}

说明

  • 表示函数或方法
  • 包含函数签名

方法

  • Parent() *Scope
  • Pos() token.Pos
  • Pkg() *Package
  • Name() string
  • Type() Type
  • Exported() bool
  • String() string
  • Scope() *Scope
  • FullName() string

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建函数签名
    sig := types.NewSignature(nil,
        types.NewTuple(types.NewVar(0, nil, "a", types.Typ[types.Int])),
        types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])),
        false)
    
    // 创建函数
    fn := types.NewFunc(0, nil, "Add", sig)
    
    fmt.Printf("函数:%s\n", fn.Name())
    fmt.Printf("类型:%s\n", fn.Type())
    fmt.Printf("全名:%s\n", fn.FullName())
}

TypeName 类型

TypeName

定义

type TypeName struct {
    // 内部字段
}

说明

  • 表示类型名称
  • 用于命名类型

方法

  • Parent() *Scope
  • Pos() token.Pos
  • Pkg() *Package
  • Name() string
  • Type() Type
  • Exported() bool
  • String() string
  • IsAlias() bool

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 创建类型名称
    typeName := types.NewTypeName(0, nil, "MyType", nil)
    
    fmt.Printf("名称:%s\n", typeName.Name())
    fmt.Printf("导出:%v\n", typeName.Exported())
    fmt.Printf("别名:%v\n", typeName.IsAlias())
}

Const 类型(常量)

Const

定义

type Const struct {
    // 内部字段
}

说明

  • 表示常量
  • 包含常量值

方法

  • Parent() *Scope
  • Pos() token.Pos
  • Pkg() *Package
  • Name() string
  • Type() Type
  • Exported() bool
  • String() string
  • Val() constant.Value

示例

package main

import (
    "fmt"
    "go/constant"
    "go/types"
)

func main() {
    // 创建常量
    val := constant.MakeInt64(42)
    c := types.NewConst(0, nil, "Answer", types.Typ[types.Int], val)
    
    fmt.Printf("常量:%s\n", c.Name())
    fmt.Printf("类型:%s\n", c.Type())
    fmt.Printf("值:%s\n", c.Val())
}

运行

$ go run main.go
常量:Answer
类型:int
值:42

Builtin 类型(内置函数)

Builtin

定义

type Builtin struct {
    // 内部字段
}

说明

  • 表示内置函数(len, cap, append 等)
  • 在全局作用域中

方法

  • Parent() *Scope
  • Pos() token.Pos
  • Pkg() *Package
  • Name() string
  • Type() Type
  • Exported() bool
  • String() string

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 查找内置函数
    lenObj := types.Universe.Lookup("len")
    appendObj := types.Universe.Lookup("append")
    
    fmt.Printf("len: %s\n", lenObj.Type())
    fmt.Printf("append: %s\n", appendObj.Type())
}

运行

$ go run main.go
len: func([]T) int
append: func([]T ...T) []T

Nil 类型(nil 对象)

Nil

定义

type Nil struct {
    // 内部字段
}

说明

  • 表示 nil 值
  • 特殊的对象

三、Config 和 Info 结构体

Config 结构体

Config

定义

type Config struct {
    IgnoreFuncBodies bool
    DisableUnusedImportCheck bool
    Error func(error)
    Importer Importer
    Sizes Sizes
}

说明

  • 类型检查配置
  • 控制检查行为

字段

  • IgnoreFuncBodies:忽略函数体
  • DisableUnusedImportCheck:禁用未使用导入检查
  • Error:错误处理函数
  • Importer:包导入器
  • Sizes:类型大小计算器

方法

  • Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error)

示例

package main

import (
    "fmt"
    "go/importer"
    "go/types"
)

func main() {
    // 创建配置
    conf := types.Config{
        Importer: importer.Default(),
        Error: func(err error) {
            fmt.Printf("错误:%v\n", err)
        },
    }
    
    fmt.Printf("配置创建成功\n")
}

Info 结构体

Info

定义

type Info struct {
    Types      map[ast.Expr]TypeAndValue
    Defs       map[*ast.Ident]Object
    Uses       map[*ast.Ident]Object
    Implicits  map[ast.Node]Object
    Selections map[*ast.SelectorExpr]*Selection
    Scopes     map[ast.Node]*Scope
    InitOrder  []*InitOrder
}

说明

  • 存储类型检查信息
  • 在检查前初始化

字段

  • Types:表达式类型
  • Defs:标识符定义
  • Uses:标识符使用
  • Implicits:隐式对象
  • Selections:选择表达式
  • Scopes:作用域映射
  • InitOrder:初始化顺序

示例

package main

import (
    "go/ast"
    "go/types"
)

func createInfo() *types.Info {
    return &types.Info{
        Types: make(map[ast.Expr]types.TypeAndValue),
        Defs:  make(map[*ast.Ident]types.Object),
        Uses:  make(map[*ast.Ident]types.Object),
    }
}

TypeAndValue 结构体

TypeAndValue

定义

type TypeAndValue struct {
    Type     Type
    Value    constant.Value
    Addressable bool
    Assignable  bool
    HasOk       bool
}

说明

  • 表示表达式的类型和值
  • 包含附加信息

字段

  • Type:类型
  • Value:常量值
  • Addressable:是否可寻址
  • Assignable:是否可赋值
  • HasOk:是否有 ok 标志

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    tv := types.TypeAndValue{
        Type: types.Typ[types.Int],
    }
    
    fmt.Printf("类型:%s\n", tv.Type)
    fmt.Printf("可寻址:%v\n", tv.Addressable)
}

四、包级别函数和变量(按字母顺序)

基本类型数组

Typ

定义

var Typ [UnsafePointer + 1]*Basic

说明

  • 所有基本类型的数组
  • 通过索引访问

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 访问基本类型
    fmt.Printf("int: %s\n", types.Typ[types.Int])
    fmt.Printf("string: %s\n", types.Typ[types.String])
    fmt.Printf("bool: %s\n", types.Typ[types.Bool])
}

宇宙作用域

Universe

定义

var Universe *Scope

说明

  • 全局宇宙作用域
  • 包含所有内置对象

示例

package main

import (
    "fmt"
    "go/types"
)

func main() {
    // 查找内置对象
    lenObj := types.Universe.Lookup("len")
    errorObj := types.Universe.Lookup("error")
    trueObj := types.Universe.Lookup("true")
    
    fmt.Printf("len: %s\n", lenObj.Type())
    fmt.Printf("error: %s\n", errorObj.Type())
    fmt.Printf("true: %s\n", trueObj.Type())
}

运行

$ go run main.go
len: func([]T) int
error: interface{Error() string}
true: untyped bool

查找对象

Lookup

定义

func (scope *Scope) Lookup(name string) Object

说明

  • 在当前作用域查找对象
  • 不搜索父作用域

创建数组类型

NewArray

定义

func NewArray(elem Type, len int64) *Array

说明

  • 创建数组类型

创建 Channel 类型

NewChan

定义

func NewChan(dir ChanDir, elem Type) *Chan

说明

  • 创建 Channel 类型

创建接口类型

NewInterfaceType

定义

func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface

说明

  • 创建接口类型

创建 Map 类型

NewMap

定义

func NewMap(key, elem Type) *Map

说明

  • 创建 Map 类型

创建命名类型

NewNamed

定义

func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named

说明

  • 创建命名类型

创建指针类型

NewPointer

定义

func NewPointer(elem Type) *Pointer

说明

  • 创建指针类型

创建作用域

NewScope

定义

func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope

说明

  • 创建新作用域

创建切片类型

NewSlice

定义

func NewSlice(elem Type) *Slice

说明

  • 创建切片类型

创建结构体类型

NewStruct

定义

func NewStruct(fields []*Var, tags []string) *Struct

说明

  • 创建结构体类型

创建函数签名

NewSignature

定义

func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature

说明

  • 创建函数签名

创建元组

NewTuple

定义

func NewTuple(x ...*Var) *Tuple

说明

  • 创建元组(可变参数)

类型检查

Check

定义

func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error)

说明

  • 类型检查包
  • 最常用的函数

五、快速参考

Type 接口实现

类型说明示例
Basic基本类型int, string, bool
Array数组类型[10]int
Slice切片类型[]string
MapMap 类型map[string]int
Struct结构体类型struct{Name string}
Pointer指针类型*int
Signature函数签名func(int) int
Interface接口类型interface{Read()}
ChanChannel 类型chan int
Tuple元组类型(int, string)
Named命名类型type MyInt int

Object 接口实现

类型说明示例
Packagefmt, net/http
Var变量x int, 字段,参数
Func函数func Add()
TypeName类型名type MyType
Const常量const Pi = 3.14
Builtin内置函数len, append
Nilnil 值nil

包级别变量

变量类型说明
Typ[]*Basic基本类型数组
Universe*Scope宇宙作用域

包级别函数

函数说明
NewArray(elem, len)创建数组类型
NewChan(dir, elem)创建 Channel 类型
NewMap(key, elem)创建 Map 类型
NewPointer(elem)创建指针类型
NewSlice(elem)创建切片类型
NewStruct(fields, tags)创建结构体类型
NewSignature(recv, params, results, variadic)创建函数签名
NewTuple(x…)创建元组
NewNamed(obj, underlying, methods)创建命名类型
NewInterfaceType(methods, embeddeds)创建接口类型
NewScope(parent, pos, end, comment)创建作用域
conf.Check(path, fset, files, info)类型检查

类型创建函数

类型创建函数
ArrayNewArray(elem, len)
SliceNewSlice(elem)
MapNewMap(key, elem)
PointerNewPointer(elem)
ChanNewChan(dir, elem)
StructNewStruct(fields, tags)
SignatureNewSignature(recv, params, results, variadic)
NamedNewNamed(obj, underlying, methods)

使用场景

场景推荐函数/方法
类型检查conf.Check()
获取表达式类型info.Types[expr]
查找定义info.Defs[ident]
查找使用info.Uses[ident]
创建类型New* 系列函数
查找内置对象Universe.Lookup()
作用域查找scope.Lookup()

六、最佳实践

1. 基本类型检查

package main

import (
    "go/ast"
    "go/importer"
    "go/parser"
    "go/token"
    "go/types"
)

func typeCheck(src []byte) error {
    fset := token.NewFileSet()
    file, _ := parser.ParseFile(fset, "", src, parser.ParseComments)
    
    conf := types.Config{
        Importer: importer.Default(),
    }
    
    info := &types.Info{
        Types: make(map[ast.Expr]types.TypeAndValue),
        Defs:  make(map[*ast.Ident]types.Object),
    }
    
    _, err := conf.Check("main", fset, []*ast.File{file}, info)
    return err
}

2. 收集类型信息

func collectTypeInfo(info *types.Info) {
    for expr, tv := range info.Types {
        // 处理每个表达式的类型
        _ = expr
        _ = tv.Type
    }
    
    for ident, obj := range info.Defs {
        if obj != nil {
            // 处理定义
            _ = ident
            _ = obj
        }
    }
}

3. 错误处理

func checkWithErrors(src []byte) {
    var errors []error
    
    conf := types.Config{
        Importer: importer.Default(),
        Error: func(err error) {
            errors = append(errors, err)
        },
    }
    
    // ... 执行检查
    
    if len(errors) > 0 {
        // 处理错误
    }
}

最后更新:2026-04-04
Go 版本:Go 1.23+