2022å¹´8æãGo 1.18対å¿çã«ã¢ãããã¼ããã¾ãã
ä¹ ãã¶ãã®Goãã¿ã§ããGo 5 Advent Calendar 2020ã®18æ¥ç®ã空ãã¦ããã®ã§æ¸ãã¾ããã
Goã§å®è£ ãããã³ãã³ãã§ã¯ããã«ãããæç¹ã®ãã¼ã¸ã§ã³ãåãè¾¼ããã以ä¸ã®ãããªMakefileãç¨æãããã¨ãããã¨æãã¾ãã
.PHONY: build build: go build -ldflags '-X main.Version=$(VERSION)'
ããããã®æ¹æ³ã§ã¯ãgo install
ãªã©Makefileãçµç±ãããã«ããããã¤ããªã«ã¯é©åãªãã¼ã¸ã§ã³ãåãè¾¼ã¾ããªãåé¡ãããã¾ããå人çãªæè¦ã§ã¯ãå¯è½ãªéãgo get
ã§ã¤ã³ã¹ãã¼ã«ã§ããç¶æ
ãç¶æããæ¹ãè¯ãã¨æã£ã¦ãã¾ããããã¼ã¸ã§ã³ãåãè¾¼ãããã«ã¯ä»ã«æ¹æ³ããªãã®ã§ä»æ¹ããªãã¨ç解ãã¦ãã¾ããããããGo 1.19ç¾å¨ãruntime/debug.ReadBuildInfoã使ãã¨ãGoã¢ã¸ã¥ã¼ã«ã§ç®¡çãããå ´åã«ããã¦ã¯ãã«ãæã®ãã¼ã¸ã§ã³ãåããããã«ãªã£ã¦ãã¦ãããã使ãã°èªåã§ãã¼ã¸ã§ã³ãåãè¾¼ãå¿
è¦ããªããªãã®ã§ãgo install
ã ãã§é©åãªãã¼ã¸ã§ã³ã表示ããããã¨ãã§ãã¾ãã
ãã¼ã¸ã§ã³ã®åå¾
ãã¼ã¸ã§ã³ãåå¾ãããç®æã§ã以ä¸ã®ããã«æ¸ãã¾ãããã
import ( "runtime/debug" ) func Version() string { info, ok := debug.ReadBuildInfo() if !ok { // Goã¢ã¸ã¥ã¼ã«ãç¡å¹ãªã© return "(devel)" } return info.Main.Version }
ããã§ãv1.0.0ãªã©ã®ãããªãGoã¢ã¸ã¥ã¼ã«ãèªèãã¦ãããã¼ã¸ã§ã³æååãåå¾ã§ãã¾ããç°¡åã§ããã
runtime/debug.BuildInfoæ§é ä½
Go 1.19æç¹ã®å®ç¾©ã¯ä»¥ä¸ã®ããã«ãªã£ã¦ãã¦ãmainããã±ã¼ã¸ã®ãã¼ã¸ã§ã³ä»¥å¤ã«ããã³ãã³ããä¾åãã¦ããã¢ã¸ã¥ã¼ã«ã®importãã¹ããã¼ã¸ã§ã³ãåå¾ã§ãã¾ãããã ããruntime/debug.BuildInfoã«å«ã¾ããã¢ã¸ã¥ã¼ã«ã¯ã³ãã³ãããã«ãããããã«å¿ è¦ãªãã®ã ãã§ããä¾ãã°ãã¹ãã§ã®ã¿åç §ããã¢ã¸ã¥ã¼ã«ã¯å«ã¾ãã¾ããã
type BuildInfo struct { GoVersion string // Version of Go that produced this binary. Path string // The main package path Main Module // The module containing the main package Deps []*Module // Module dependencies Settings []BuildSetting // Other information about the build. } type Module struct { Path string // module path Version string // module version Sum string // checksum Replace *Module // replaced by this module } type BuildSetting struct { // 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 }
BuildSettingã¯ããã«ãããã¨ãã®ãã©ã°ããªãã¸ããªã®æ å ±ãæã£ãå¤ã§ããGo 1.18æç¹ã§ã¯ä»¥ä¸ã®ãããªå¤ãä¿æãã¦ãã¾ãã
// Key=Valueã§åæ -compiler=gc CGO_ENABLED=1 CGO_CFLAGS= CGO_CPPFLAGS= CGO_CXXFLAGS= CGO_LDFLAGS= GOARCH=amd64 GOOS=linux GOAMD64=v1 vcs=git vcs.revision=ddf71bc3f52c7c221cea82bd26547d0346715f14 vcs.time=2020-12-17T05:50:03Z vcs.modified=true
å¾ã£ã¦ãã³ãããããã·ã¥ãBuildInfoããåç §ãããã¨ãå¯è½ã§ãã
ã©ã®ããã«åãã®ã
ãã®æ¹æ³ãå°å ¥ããå ´åã«ããã¼ã¸ã§ã³è¡¨è¨ã¯ã©ããªãã®ããããã¤ãã®ãã¿ã¼ã³ã§è¦ã¦ããã¾ãããã
æ®éã«go installããå ´å
ã³ãã³ãã®importãã¹ããã®ã¾ã¾go get
ããå ´åã§ããããã®å ´åã¯ãGoã¢ã¸ã¥ã¼ã«ãèªèããææ°ã®ãã¼ã¸ã§ã³ã使ããã¾ãã
% go install github.com/lufia/go-version-example go: downloading github.com/lufia/go-version-example v0.0.2 go: github.com/lufia/go-version-example upgrade => v0.0.2 go: downloading github.com/pkg/errors v0.9.1 % go-version-example Main = v0.0.2 Deps[github.com/pkg/errors] = v0.9.1
å¤ããã¼ã¸ã§ã³ãæå®ããå ´å
ãã®å ´åããæ£ãããã¼ã¸ã§ã³ãåå¾ã§ãã¾ãã
% go install github.com/lufia/go-version-example@v0.0.1 go install github.com/lufia/go-version-example@v0.0.1 go: downloading github.com/lufia/go-version-example v0.0.1 % go-version-example Main = v0.0.1
ãã©ã³ãåãªã©ãæè¨ããå ´å
æ£è¦ã®ãã¼ã¸ã§ã³ããmainãã©ã³ããé²ãã§ããå ´åã«ã@mainãæè¨ãã¦go get
ããå ´åã¯ãã¼ã¸ã§ã³ã®å¾ãã«æå»ã¨ããã·ã¥å¤ãä»ä¸ããã¾ãã
% go install github.com/lufia/go-version-example@main go: downloading github.com/lufia/go-version-example v0.0.2-0.20201217055003-ddf71bc3f52c go: github.com/lufia/go-version-example main => v0.0.2-0.20201217055003-ddf71bc3f52c % go-version-example Main = v0.0.2-0.20201217055003-ddf71bc3f52c Deps[github.com/pkg/errors] = v0.9.1
ã«ã¬ã³ããã£ã¬ã¯ããªãmainã¢ã¸ã¥ã¼ã«ã¨åãå ´å
å°ãåããã¥ããã®ã§ãããã«ã¬ã³ããã£ã¬ã¯ããªãGoã¢ã¸ã¥ã¼ã«ç®¡çä¸ã«ããããã®importãã¹ã¨go get
ããimportãã¹ãåä¸ã®å ´åãä¾ãã°ã
// go.mod module github.com/lufia/go-version-example
ãæã¤ãªãã¸ããªã®ä¸ã§
% go install github.com/lufia/go-version-example
ã¨ãã¦ã³ãã³ãããã«ãããå ´åããã®ã¨ãã¯æå ã§ã©ã®ãããªã¿ã°ä»ããããã¦ããã¨ãã¦ããmainã®ãã¼ã¸ã§ã³ã¯å¸¸ã«(devel)ã¨ããæååãåå¾ããã¾ããMakefileã¨ä½µç¨ãããã¨ããã¨æå ã«ã¯ã½ã¼ã¹ã³ã¼ããä¸å¼ããã¯ããªã®ã§ããã®æåã¯å°ãåä»ã§ãã*1ã
% cd $GOPATH/src/github.com/lufia/go-version-example % go install github.com/lufia/go-version-example % go-version-example Main = (devel) Deps[github.com/pkg/errors] = v0.9.1
ã©ããã£ã¦ããã®ã
2020-12-18 16:30: 対å¿ãã©ã¼ãããã®è©±ã¯go version -m
ã®è©±ã ã£ãã®ã§æ¸ãæãã¾ããã
runtime/debug.ReadBuildInfoã¯ä½ãèªãã§ããã®ããã§ããããã«ãæã«runtime.modinfoã¸ã¢ã¸ã¥ã¼ã«æ å ±ãåãè¾¼ã¾ãã¦ãã¦ããããruntime/debug.BuildInfoã¸ãã¼ã¹ãã¦ããããã§ãããé°å²æ°ã§èªãã æãã ã¨ãåãè¾¼ãã§ããã®ã¯go/src/cmd/go/internal/work/exec.goã®build()辺ãããªã
runtime.modinfoã¨ã ãããåãå¤ãgo version -m
ã§èª¿ã¹ããã¨ãã§ãã¾ãããã£ã¡ã¯Go 1.13以éã§å¯¾å¿ããã¾ããã
% go version -m ~/bin/ivy /Users/lufia/bin/ivy: go1.14.6 path robpike.io/ivy mod robpike.io/ivy v0.0.0-20191204195242-5feaa23cbcf3 h1:tff9UcwX5PKD7Z+Q7O9EIILnQVm5uRY0/xP90+oXtog=
go version
ãèªãæ
å ±ã¯ãä¾ãã°ELFãã©ã¼ãããã®ãã¤ããªã§ã¯.go.buildinfo
ã¨ããååã®ã»ã¯ã·ã§ã³ã«64KBã®ãã¼ã¿ã¨ãã¦åå¨ãã¾ããMach-Oã®å ´åã¯ã»ã¯ã·ã§ã³åã__go_buildinfo
ã§ãã£ãããªã©è¥å¹²ã®å·®ã¯ããã¾ãããã©ããåããã¼ã¿ãåãè¾¼ã¾ãã¦ãã¾ãããããã®è©³ç´°ã¯ãgo/src/cmd/go/internal/version以ä¸ã®ã½ã¼ã¹ã³ã¼ããçºããã¨è¯ãã§ãããã
ä»ã®å®è¡ãã¡ã¤ã«ã«å«ã¾ãããã¼ã¸ã§ã³ã調ã¹ããå ´å
Go 1.18ãããdebug/buildinfoããã±ã¼ã¸ã使ãã¨ãgo version -m
ã¨åæ§ã«æå®ãããã¡ã¤ã«ã®ãã¼ã¸ã§ã³ã調ã¹ããã¨ãã§ããããã«ãªãã¾ãããããããã®å¤ã¯ä¸ã¨åããªã®ã§ã³ã¼ãã ãç´¹ä»ãã¾ãã
package main import ( "debug/buildinfo" "flag" "fmt" "log" ) func main() { log.SetFlags(0) flag.Parse() for _, arg := range flag.Args() { info, err := buildinfo.ReadFile(arg) if err != nil { log.Fatalln("can't get BuildInfo:", err) } fmt.Printf("Main = %s (%s)\n", info.Main.Version, info.Main.Sum) for _, m := range info.Deps { fmt.Printf("Deps[%s] = %s (%s)\n", m.Path, m.Version, m.Sum) } fmt.Println("Settings:") for _, s := range info.Settings { fmt.Printf("\t%s=%s\n", s.Key, s.Value) } } }
ã¾ã¨ã
runtime/debug.ReadBuildInfoã§ã³ãã³ãã«åãè¾¼ã¾ãããã¼ã¸ã§ã³ãåå¾ã§ãããã¨ãç´¹ä»ãã¾ãããå¤ãã®å ´åã¯ãããã使ãã¨go install
ã ãã§ãé©åãªãã¼ã¸ã§ã³ãåå¾ã§ããã¨æãã¾ããå人çã«ã¯go install
ã§ã³ãã³ããå°å
¥ãããã¨ãå¤ãããã®ã§ãMakefileã«ä¾åããªããã®æ¹æ³ãåºã¾ã£ã¦ãããã¨å¬ããã®ã§ãããMakefileã§ã¯ãã¹ã³ã³ãã¤ã«ãã¦ããå ´åã¯å®¹æã«(devel)表è¨ã¨ãªã£ã¦ãã¾ãã¨ããã¯ãå°ã注æãå¿
è¦ããããã¾ãããã
*1:ä¸æçã«cdã§ã«ã¬ã³ããã£ã¬ã¯ããªãå¤æ´ããã°åé¿ã¯å¯è½ã§ãã