Involved Source Files
Package gcexportdata provides functions for locating, reading, and
writing export data files containing type information produced by the
gc compiler. This package supports go1.7 export data format and all
later versions.
Although it might seem convenient for this package to live alongside
go/types in the standard library, this would cause version skew
problems for developer tools that use it, since they must be able to
consume the outputs of the gc compiler both before and after a Go
update such as from Go 1.7 to Go 1.8. Because this package lives in
golang.org/x/tools, sites can update their version of this repo some
time before the Go 1.8 release and rebuild and redeploy their
developer tools, which will then be able to consume both Go 1.7 and
Go 1.8 export data files, so they will work before and after the
Go update. (See discussion at https://golang.org/issue/15651.)
importer.go
Code Examples
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"go/types"
"golang.org/x/tools/go/gcexportdata"
"log"
"path/filepath"
)
func main() {
const src = `package myrpc
// choosing a package that doesn't change across releases
import "net/rpc"
const serverError rpc.ServerError = ""
`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "myrpc.go", src, 0)
if err != nil {
log.Fatal(err)
}
packages := make(map[string]*types.Package)
imp := gcexportdata.NewImporter(fset, packages)
conf := types.Config{Importer: imp}
pkg, err := conf.Check("myrpc", fset, []*ast.File{f}, nil)
if err != nil {
log.Fatal(err)
}
// object from imported package
pi := packages["net/rpc"].Scope().Lookup("ServerError")
fmt.Printf("type %s.%s %s // %s\n",
pi.Pkg().Path(),
pi.Name(),
pi.Type().Underlying(),
slashify(fset.Position(pi.Pos())),
)
// object in source package
twopi := pkg.Scope().Lookup("serverError")
fmt.Printf("const %s %s = %s // %s\n",
twopi.Name(),
twopi.Type(),
twopi.(*types.Const).Val(),
slashify(fset.Position(twopi.Pos())),
)
}
func slashify(posn token.Position) token.Position {
posn.Filename = filepath.ToSlash(posn.Filename)
return posn
}
package main
import (
"fmt"
"go/token"
"go/types"
"golang.org/x/tools/go/gcexportdata"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
// Find the export data file.
filename, path := gcexportdata.Find("fmt", "")
if filename == "" {
log.Fatalf("can't find export data for fmt")
}
fmt.Printf("Package path: %s\n", path)
// Open and read the file.
f, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer f.Close()
r, err := gcexportdata.NewReader(f)
if err != nil {
log.Fatalf("reading export data %s: %v", filename, err)
}
// Decode the export data.
fset := token.NewFileSet()
imports := make(map[string]*types.Package)
pkg, err := gcexportdata.Read(r, fset, imports, path)
if err != nil {
log.Fatal(err)
}
// We can see all the names in Names.
members := pkg.Scope().Names()
foundPrintln := false
for _, member := range members {
if member == "Println" {
foundPrintln = true
break
}
}
fmt.Print("Package members: ")
if foundPrintln {
fmt.Println("Println found")
} else {
fmt.Println("Println not found")
}
// We can also look up a name directly using Lookup.
println := pkg.Scope().Lookup("Println")
// go 1.18+ uses the 'any' alias
typ := strings.ReplaceAll(println.Type().String(), "interface{}", "any")
fmt.Printf("Println type: %s\n", typ)
posn := fset.Position(println.Pos())
// make example deterministic
posn.Line = 123
fmt.Printf("Println location: %s\n", slashify(posn))
}
func slashify(posn token.Position) token.Position {
posn.Filename = filepath.ToSlash(posn.Filename)
return posn
}
Package-Level Type Names (only one, which is unexported)
Package-Level Functions (total 8, in which 7 are exported)
Find returns the name of an object (.o) or archive (.a) file
containing type information for the specified import path,
using the go command.
If no file was found, an empty filename is returned.
A relative srcDir is interpreted relative to the current working directory.
Find also returns the package's resolved (canonical) import path,
reflecting the effects of srcDir and vendoring on importPath.
Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,
which is more efficient.
NewImporter returns a new instance of the types.Importer interface
that reads type information from export data files written by gc.
The Importer also satisfies types.ImporterFrom.
Export data files are located using "go build" workspace conventions
and the build.Default context.
Use this importer instead of go/importer.For("gc", ...) to avoid the
version-skew problems described in the documentation of this package,
or to control the FileSet or access the imports map populated during
package loading.
Deprecated: Use the higher-level API in golang.org/x/tools/go/packages,
which is more efficient.
NewReader returns a reader for the export data section of an object
(.o) or archive (.a) file read from r. The new reader may provide
additional trailing data beyond the end of the export data.
Read reads export data from in, decodes it, and returns type
information for the package.
The package path (effectively its linker symbol prefix) is
specified by path, since unlike the package name, this information
may not be recorded in the export data.
File position information is added to fset.
Read may inspect and add to the imports map to ensure that references
within the export data to other packages are consistent. The caller
must ensure that imports[path] does not exist, or exists but is
incomplete (see types.Package.Complete), and Read inserts the
resulting package into this map entry.
On return, the state of the reader is undefined.
ReadBundle reads an export bundle from in, decodes it, and returns type
information for the packages.
File position information is added to fset.
ReadBundle may inspect and add to the imports map to ensure that references
within the export bundle to other packages are consistent.
On return, the state of the reader is undefined.
Experimental: This API is experimental and may change in the future.
Write writes encoded type information for the specified package to out.
The FileSet provides file position information for named objects.
WriteBundle writes encoded type information for the specified packages to out.
The FileSet provides file position information for named objects.
Experimental: This API is experimental and may change in the future.
readAll works the same way as io.ReadAll, but avoids allocations and copies
by preallocating a byte slice of the necessary size if the size is known up
front. This is always possible when the input is an archive. In that case,
NewReader will return the known size using an io.LimitedReader.
The pages are generated with Goldsv0.4.9. (GOOS=linux GOARCH=amd64)