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() TypeString() stringKind() BasicKindInfo() BasicInfoName() 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() TypeString() stringElem() TypeLen() 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() TypeString() stringElem() 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() TypeString() stringKey() TypeElem() TypeIsComparable() 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() TypeString() stringNumFields() intField(i int) *VarTag(i int) stringIsComparable() 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() TypeString() stringElem() 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() TypeString() stringParams() *TupleResults() *TupleRecv() *VarVariadic() 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() TypeString() stringNumMethods() intMethod(i int) *FuncNumEmbeddeds() intEmbedded(i int) TypeIsComparable() 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() TypeString() stringElem() TypeDir() 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() TypeString() stringLen() intAt(i int) *VarVariables() []*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() TypeString() stringObj() *TypeNameNumMethods() intMethod(i int) *FuncSetUnderlying(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() stringPath() stringScope() *ScopeImports() []*PackageComplete() boolMarkComplete()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() *ScopeChild(i int) *ScopeNumChildren() intInsert(obj Object) ObjectLookup(name string) ObjectLookupParent(name string, pos token.Pos) (*Scope, Object)Names() []stringContains(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() *ScopePos() token.PosPkg() *PackageName() stringType() TypeExported() boolString() stringIsField() boolAnonymous() 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() *ScopePos() token.PosPkg() *PackageName() stringType() TypeExported() boolString() stringScope() *ScopeFullName() 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() *ScopePos() token.PosPkg() *PackageName() stringType() TypeExported() boolString() stringIsAlias() 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() *ScopePos() token.PosPkg() *PackageName() stringType() TypeExported() boolString() stringVal() 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() *ScopePos() token.PosPkg() *PackageName() stringType() TypeExported() boolString() 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 |
| Map | Map 类型 | map[string]int |
| Struct | 结构体类型 | struct{Name string} |
| Pointer | 指针类型 | *int |
| Signature | 函数签名 | func(int) int |
| Interface | 接口类型 | interface{Read()} |
| Chan | Channel 类型 | chan int |
| Tuple | 元组类型 | (int, string) |
| Named | 命名类型 | type MyInt int |
Object 接口实现
| 类型 | 说明 | 示例 |
|---|---|---|
| Package | 包 | fmt, net/http |
| Var | 变量 | x int, 字段,参数 |
| Func | 函数 | func Add() |
| TypeName | 类型名 | type MyType |
| Const | 常量 | const Pi = 3.14 |
| Builtin | 内置函数 | len, append |
| Nil | nil 值 | 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) | 类型检查 |
类型创建函数
| 类型 | 创建函数 |
|---|---|
| Array | NewArray(elem, len) |
| Slice | NewSlice(elem) |
| Map | NewMap(key, elem) |
| Pointer | NewPointer(elem) |
| Chan | NewChan(dir, elem) |
| Struct | NewStruct(fields, tags) |
| Signature | NewSignature(recv, params, results, variadic) |
| Named | NewNamed(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+