GO语言"go/types"包中"Info"类型的用法及代码示例。
Info 保存type-checked 包的结果类型信息。仅收集为其提供Map的信息。如果包有类型错误,收集的信息可能不完整。
用法:
type Info struct {
// Types maps expressions to their types, and for constant
// expressions, also their values.Invalid expressions are
// omitted.
//
// For(possibly parenthesized) identifiers denoting built-in
// functions, the recorded signatures are call-site specific:
// if the call result is not a constant, the recorded type is
// an argument-specific signature.Otherwise, the recorded type
// is invalid.
//
// The Types map does not record the type of every identifier,
// only those that appear where an arbitrary expression is
// permitted.For instance, the identifier f in a selector
// expression x.f is found only in the Selections map, the
// identifier z in a variable declaration 'var z int' is found
// only in the Defs map, and identifiers denoting packages in
// qualified identifiers are collected in the Uses map.
Types map[ast.Expr]TypeAndValue
// Instances maps identifiers denoting generic types or functions to their
// type arguments and instantiated type.
//
// For example, Instances will map the identifier for 'T' in the type
// instantiation T[int, string] to the type arguments [int, string] and
// resulting instantiated *Named type.Given a generic function
// func F[A any](A), Instances will map the identifier for 'F' in the call
// expression F(int(1)) to the inferred type arguments [int], and resulting
// instantiated *Signature.
//
// Invariant: Instantiating Uses[id].Type() with Instances[id].TypeArgs
// results in an equivalent of Instances[id].Type.
Instances map[*ast.Ident]Instance // Go 1.18
// Defs maps identifiers to the objects they define(including
// package names, dots "." of dot-imports, and blank "_" identifiers).
// For identifiers that do not denote objects(e.g., the package name
// in package clauses, or symbolic variables t in t := x.(type) of
// type switch headers), the corresponding objects are nil.
//
// For an embedded field, Defs returns the field *Var it defines.
//
// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
Defs map[*ast.Ident]Object
// Uses maps identifiers to the objects they denote.
//
// For an embedded field, Uses returns the *TypeName it denotes.
//
// Invariant: Uses[id].Pos() != id.Pos()
Uses map[*ast.Ident]Object
// Implicits maps nodes to their implicitly declared objects, if any.
// The following node and object types may appear:
//
// node declared object
//
// *ast.ImportSpec *PkgName for imports without renames
// *ast.CaseClause type-specific *Var for each type switch case clause(incl.default)
// *ast.Field anonymous parameter *Var(incl.unnamed results)
//
Implicits map[ast.Node]Object
// Selections maps selector expressions(excluding qualified identifiers)
// to their corresponding selections.
Selections map[*ast.SelectorExpr]*Selection
// Scopes maps ast.Nodes to the scopes they define.Package scopes are not
// associated with a specific node but with all files belonging to a package.
// Thus, the package scope can be found in the type-checked Package object.
// Scopes nest, with the Universe scope being the outermost scope, enclosing
// the package scope, which contains(one or more) files scopes, which enclose
// function scopes which in turn enclose statement and function literal scopes.
// Note that even though package-level functions are declared in the package
// scope, the function scopes are embedded in the file scope of the file
// containing the function declaration.
//
// The following node types may appear in Scopes:
//
// *ast.File
// *ast.FuncType
// *ast.TypeSpec
// *ast.BlockStmt
// *ast.IfStmt
// *ast.SwitchStmt
// *ast.TypeSwitchStmt
// *ast.CaseClause
// *ast.CommClause
// *ast.ForStmt
// *ast.RangeStmt
//
Scopes map[ast.Node]*Scope
// InitOrder is the list of package-level initializers in the order in which
// they must be executed.Initializers referring to variables related by an
// initialization dependency appear in topological order, the others appear
// in source order.Variables without an initialization expression do not
// appear in this list.
InitOrder []*Initializer
}
例子:
ExampleInfo 打印类型检查器在 types.Info 结构中记录的各种事实:每个命名对象的定义和引用,以及包中每个表达式的类型、值和模式。
package main
import (
"bytes"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/token"
"go/types"
"log"
"sort"
"strings"
)
func main() {
// Parse a single source file.
const input = `
package fib
type S string
var a, b, c = len(b), S(c), "hello"
func fib(x int) int {
if x < 2 {
return x
}
return fib(x-1) - fib(x-2)
}`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "fib.go", input, 0)
if err != nil {
log.Fatal(err)
}
// Type-check the package.
// We create an empty map for each kind of input
// we're interested in, and Check populates them.
info := types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
Defs: make(map[*ast.Ident]types.Object),
Uses: make(map[*ast.Ident]types.Object),
}
var conf types.Config
pkg, err := conf.Check("fib", fset, []*ast.File{f}, &info)
if err != nil {
log.Fatal(err)
}
// Print package-level variables in initialization order.
fmt.Printf("InitOrder: %v\n\n", info.InitOrder)
// For each named object, print the line and
// column of its definition and each of its uses.
fmt.Println("Defs and Uses of each named object:")
usesByObj := make(map[types.Object][]string)
for id, obj := range info.Uses {
posn := fset.Position(id.Pos())
lineCol := fmt.Sprintf("%d:%d", posn.Line, posn.Column)
usesByObj[obj] = append(usesByObj[obj], lineCol)
}
var items []string
for obj, uses := range usesByObj {
sort.Strings(uses)
item := fmt.Sprintf("%s:\n defined at %s\n used at %s",
types.ObjectString(obj, types.RelativeTo(pkg)),
fset.Position(obj.Pos()),
strings.Join(uses, ", "))
items = append(items, item)
}
sort.Strings(items) // sort by line:col, in effect
fmt.Println(strings.Join(items, "\n"))
fmt.Println()
fmt.Println("Types and Values of each expression:")
items = nil
for expr, tv := range info.Types {
var buf bytes.Buffer
posn := fset.Position(expr.Pos())
tvstr := tv.Type.String()
if tv.Value != nil {
tvstr += " = " + tv.Value.String()
}
// line:col | expr | mode : type = value
fmt.Fprintf(&buf, "%2d:%2d | %-19s | %-7s : %s",
posn.Line, posn.Column, exprString(fset, expr),
mode(tv), tvstr)
items = append(items, buf.String())
}
sort.Strings(items)
fmt.Println(strings.Join(items, "\n"))
}
func mode(tv types.TypeAndValue) string {
switch {
case tv.IsVoid():
return "void"
case tv.IsType():
return "type"
case tv.IsBuiltin():
return "builtin"
case tv.IsNil():
return "nil"
case tv.Assignable():
if tv.Addressable() {
return "var"
}
return "mapindex"
case tv.IsValue():
return "value"
default:
return "unknown"
}
}
func exprString(fset *token.FileSet, expr ast.Expr) string {
var buf bytes.Buffer
format.Node(&buf, fset, expr)
return buf.String()
}
输出:
InitOrder: [c = "hello" b = S(c) a = len(b)] Defs and Uses of each named object: builtin len: defined at - used at 6:15 func fib(x int) int: defined at fib.go:8:6 used at 12:20, 12:9 type S string: defined at fib.go:4:6 used at 6:23 type int: defined at - used at 8:12, 8:17 type string: defined at - used at 4:8 var b S: defined at fib.go:6:8 used at 6:19 var c string: defined at fib.go:6:11 used at 6:25 var x int: defined at fib.go:8:10 used at 10:10, 12:13, 12:24, 9:5 Types and Values of each expression: 4: 8 | string | type : string 6:15 | len | builtin : func(fib.S) int 6:15 | len(b) | value : int 6:19 | b | var : fib.S 6:23 | S | type : fib.S 6:23 | S(c) | value : fib.S 6:25 | c | var : string 6:29 | "hello" | value : string = "hello" 8:12 | int | type : int 8:17 | int | type : int 9: 5 | x | var : int 9: 5 | x < 2 | value : untyped bool 9: 9 | 2 | value : int = 2 10:10 | x | var : int 12: 9 | fib | value : func(x int) int 12: 9 | fib(x - 1) | value : int 12: 9 | fib(x-1) - fib(x-2) | value : int 12:13 | x | var : int 12:13 | x - 1 | value : int 12:15 | 1 | value : int = 1 12:20 | fib | value : func(x int) int 12:20 | fib(x - 2) | value : int 12:24 | x | var : int 12:24 | x - 2 | value : int 12:26 | 2 | value : int = 2
相关用法
- GO Index.Lookup用法及代码示例
- GO IndexByte用法及代码示例
- GO Int.Scan用法及代码示例
- GO Ints用法及代码示例
- GO Intn用法及代码示例
- GO IndexFunc用法及代码示例
- GO IndexAny用法及代码示例
- GO IndexRune用法及代码示例
- GO Index用法及代码示例
- GO Int.SetString用法及代码示例
- GO Indent用法及代码示例
- GO Inspect用法及代码示例
- GO IntsAreSorted用法及代码示例
- GO Itoa用法及代码示例
- GO IP.IsPrivate用法及代码示例
- GO IsDigit用法及代码示例
- GO IP.Equal用法及代码示例
- GO IsAbs用法及代码示例
- GO IP.IsLinkLocalMulticast用法及代码示例
- GO IsGraphic用法及代码示例
注:本文由纯净天空筛选整理自golang.google.cn大神的英文原创作品 Info。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。