Involved Source Files Package gcexportdata provides functions for writing and reading
export data, a serialized representation of a [types.Package].
It describes the API of a Go package, including the names,
kinds, types, and locations of all exported declarations.
Files may be written and read using the [Write] and [Read]
functions.
Alternatively, files may be produced by the "go list -export" command.
This command runs the type checker on each specified Go package and
writes export data for each package into a file named by the Export
field of go list's -json output.
The [Read] function may then be used to read those files.
The export data format evolves with each Go release. As a matter of
policy, [Read] supports reading files produced by only the last two
Go releases plus tip; see https://go.dev/issue/68898.
The name of this package reflects its origins at a time when
cmd/compile was named gc, and [Read] parsed export data
from .a archives produced by the Go compiler.
However, starting with go1.28, the format of the files
produced by "go list -export" will diverge from the format
used by the standard Go compiler.
Consequently, this package will eventually stop being
capable of reading those files.
In the meantime, when using [Read] on a .a file written by the
compiler, be aware that export data is not at the start of the file.
Before calling Read, one must use [NewReader] to locate the export
data section of the file.
For more information on the compiler's export data, see the
"Export" section in the GOROOT/src/cmd/compile/README file.
# Deprecations
The [NewImporter], [Find], and [NewReader] functions are deprecated
and should not be used in new code.
The [WriteBundle] and [ReadBundle] functions are obsolete experiments
and are no longer supported (https://go.dev/issue/69573).importer.go
Code Examples
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"go/types"
"log"
"path/filepath"
"golang.org/x/tools/go/gcexportdata"
)
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"
"log"
"os"
"path/filepath"
"slices"
"strings"
"golang.org/x/tools/go/gcexportdata"
)
func main() {
// Build 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 := slices.Contains(members, "Println")
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 export data read from r. Export data
may be read from:
- The export data section of an object (.o) or archive file (.a).
In this case, the new reader may provide additional trailing data
beyond the end of the export data.
- The output of the cmd/export tool (e.g. via "go list -export").
In this case, the new reader contains no trailing data.
Deprecated: This package will stop supporting the reading of export
data from compiler-produced archive files in Go 1.29. To read
cmd/export files, use [Read] directly instead.
Read reads export data from in, decodes it, and returns type
information for the package.
Read is capable of reading export data produced by [Write] at the
same source code version, or by the last two Go releases (plus tip)
of the standard Go compiler. Reading files from older compilers may
produce an error.
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.
Deprecated: ReadBundle is an unsupported obsolete experimental API. It returns an error.
Write writes encoded type information for the specified package to out.
The FileSet provides file position information for named objects.
Deprecated: WriteBundle is an unsupported obsolete experimental API. It returns an error.
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.8.4. (GOOS=linux GOARCH=amd64)