// Copyright 2018 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package debugimport ()// exported from runtime.func modinfo() string// ReadBuildInfo returns the build information embedded// in the running binary. The information is available only// in binaries built with module support.func () ( *BuildInfo, bool) { := modinfo()iflen() < 32 {returnnil, false } = [16 : len()-16] , := ParseBuildInfo()if != nil {returnnil, false }// The go version is stored separately from other build info, mostly for // historical reasons. It is not part of the modinfo() string, and // ParseBuildInfo does not recognize it. We inject it here to hide this // awkwardness from the user. .GoVersion = runtime.Version()return , true}// BuildInfo represents the build information read from a Go binary.typeBuildInfostruct {// GoVersion is the version of the Go toolchain that built the binary // (for example, "go1.19.2"). GoVersion string// Path is the package path of the main package for the binary // (for example, "golang.org/x/tools/cmd/stringer"). Path string// Main describes the module that contains the main package for the binary. Main Module// Deps describes all the dependency modules, both direct and indirect, // that contributed packages to the build of this binary. Deps []*Module// Settings describes the build settings used to build the binary. Settings []BuildSetting}// A Module describes a single module included in a build.typeModulestruct { Path string// module path Version string// module version Sum string// checksum Replace *Module// replaced by this module}// A BuildSetting is a key-value pair describing one setting that influenced a build.//// Defined keys include://// - -buildmode: the buildmode flag used (typically "exe")// - -compiler: the compiler toolchain flag used (typically "gc")// - CGO_ENABLED: the effective CGO_ENABLED environment variable// - CGO_CFLAGS: the effective CGO_CFLAGS environment variable// - CGO_CPPFLAGS: the effective CGO_CPPFLAGS environment variable// - CGO_CXXFLAGS: the effective CGO_CXXFLAGS environment variable// - CGO_LDFLAGS: the effective CGO_LDFLAGS environment variable// - GOARCH: the architecture target// - GOAMD64/GOARM/GO386/etc: the architecture feature level for GOARCH// - GOOS: the operating system target// - vcs: the version control system for the source tree where the build ran// - vcs.revision: the revision identifier for the current commit or checkout// - vcs.time: the modification time associated with vcs.revision, in RFC3339 format// - vcs.modified: true or false indicating whether the source tree had local modificationstypeBuildSettingstruct {// Key and Value describe the build setting. // Key must not contain an equals sign, space, tab, or newline. // Value must not contain newlines ('\n'). Key, Value string}// quoteKey reports whether key is required to be quoted.func quoteKey( string) bool {returnlen() == 0 || strings.ContainsAny(, "= \t\r\n\"`")}// quoteValue reports whether value is required to be quoted.func quoteValue( string) bool {returnstrings.ContainsAny(, " \t\r\n\"`")}func ( *BuildInfo) () string { := new(strings.Builder)if .GoVersion != "" {fmt.Fprintf(, "go\t%s\n", .GoVersion) }if .Path != "" {fmt.Fprintf(, "path\t%s\n", .Path) }varfunc(string, Module) = func( string, Module) { .WriteString() .WriteByte('\t') .WriteString(.Path) .WriteByte('\t') .WriteString(.Version)if .Replace == nil { .WriteByte('\t') .WriteString(.Sum) } else { .WriteByte('\n') ("=>", *.Replace) } .WriteByte('\n') }if .Main != (Module{}) { ("mod", .Main) }for , := range .Deps { ("dep", *) }for , := range .Settings { := .KeyifquoteKey() { = strconv.Quote() } := .ValueifquoteValue() { = strconv.Quote() }fmt.Fprintf(, "build\t%s=%s\n", , ) }return .String()}func ( string) ( *BuildInfo, error) { := 1deferfunc() {if != nil { = fmt.Errorf("could not parse Go build info: line %d: %w", , ) } }()var ( = "path\t" = "mod\t" = "dep\t" = "=>\t" = "build\t" = "\n" = "\t" ) := func( []string) (Module, error) {iflen() != 2 && len() != 3 {returnModule{}, fmt.Errorf("expected 2 or 3 columns; got %d", len()) } := [1] := ""iflen() == 3 { = [2] }returnModule{Path: [0],Version: ,Sum: , }, nil } = new(BuildInfo)var ( *Modulestringbool )// Reverse of BuildInfo.String(), except for go version.forlen() > 0 { , , = strings.Cut(, )if ! {break }switch {casestrings.HasPrefix(, ): := [len():] .Path = string()casestrings.HasPrefix(, ): := strings.Split([len():], ) = &.Main *, = ()if != nil {returnnil, }casestrings.HasPrefix(, ): := strings.Split([len():], ) = new(Module) .Deps = append(.Deps, ) *, = ()if != nil {returnnil, }casestrings.HasPrefix(, ): := strings.Split([len():], )iflen() != 3 {returnnil, fmt.Errorf("expected 3 columns for replacement; got %d", len()) }if == nil {returnnil, fmt.Errorf("replacement with no module on previous line") } .Replace = &Module{Path: string([0]),Version: string([1]),Sum: string([2]), } = nilcasestrings.HasPrefix(, ): := [len():]iflen() < 1 {returnnil, fmt.Errorf("build line missing '='") }var , stringswitch [0] {case'=':returnnil, fmt.Errorf("build line with missing key")case'`', '"': , := strconv.QuotedPrefix()if != nil {returnnil, fmt.Errorf("invalid quoted key in build line") }iflen() == len() {returnnil, fmt.Errorf("build line missing '=' after quoted key") }if := [len()]; != '=' {returnnil, fmt.Errorf("unexpected character after quoted key: %q", ) } , _ = strconv.Unquote() = [len()+1:]default:varbool , , = strings.Cut(, "=")if ! {returnnil, fmt.Errorf("build line missing '=' after key") }ifquoteKey() {returnnil, fmt.Errorf("unquoted key %q must be quoted", ) } }varstringiflen() > 0 {switch [0] {case'`', '"':varerror , = strconv.Unquote()if != nil {returnnil, fmt.Errorf("invalid quoted value in build line") }default: = ifquoteValue() {returnnil, fmt.Errorf("unquoted value %q must be quoted", ) } } } .Settings = append(.Settings, BuildSetting{Key: , Value: }) } ++ }return , nil}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.