Go勉強の手始めに、まずはソースからインストール。
環境
- Fedora release 31
インストール手順
ソースからインストールする際の公式ドキュメントはこちら。
ツールチェインの入手
GoのコンパイラツールチェインはGoで記述されており、ツールチェインをビルドするにはGoのコンパイラが必要になる。
Goのコンパイルを行うには、この最初のビルドを行うツールチェイン (ブートストラップツールチェイン) が必要になる。
ブートストラップツールチェインもソースからコンパイルすることができるが、今回はビルド済のバイナリを入手する。
(Goをコンパイルするためにコンパイル済みのバイナリを手に入れるという行為には矛盾を感じるが)
ダウンロードページからバイナリを入手して展開する。
$ tar -xvzf go1.14.2.linux-amd64.tar.gz
$ mv go go1.14
環境変数をセットする。Goのコンパイラはツールチェインをビルドするためのブートストラップツールチェインを$GOROOT_BOOTSTRAP
から探す。
$ export GOROOT_BOOTSTRAP=/home/hidakanoko/Dev/go/go1.14
コンパイル
Goのソースコードを適当な位置にクローンする。
$ cd /home/hidakanoko/Dev/go/
$ git clone https://go.googlesource.com/go goroot
適当なバージョンをチェックアウトする。
$ cd goroot
$ git checkout go1.14.2
コンパイルを実行する。テストなども走るらしく、時間がかかる。
$ cd src
$ ./make.bash
環境変数を設定してgo
コマンドが通るか確認。
$ export PATH="$PATH:/home/hidakanoko/Dev/go/goroot/bin"
$ export GOROOT="/home/hidakanoko/Dev/go/goroot"
$ go version
go version go1.14.2 linux/amd64
無事成功。
動作確認
Goのソースをコンパイルしてみる。
package main
import "fmt"
func main() {
fmt.Println("hello, world")
}
go run
でソースのコンパイルと実行。
$ go run ~/Dev/go/test/test.go
hello, world
コマンドのヘルプはgo help run
でみられる。
$ go help run
usage: go run [build flags] [-exec xprog] package [arguments...]
(...省略)
ソースを弄ってコンパイルしてみる
せっかくなのでGoのソースを弄ってみる。
fmt.Println
は引数で与えられた文字列に改行を付与して標準出力に書き出す。
https://golang.org/pkg/fmt/#Println
Printlnは./src/fmt/print.go
に定義されている。
$ find ./ -name "*.go" | xargs grep "func Println"
(...省略)
./src/fmt/print.go:func Println(a ...interface{}) (n int, err error) {
(...省略)
Println
の定義は次のようになっている。
273 func Println(a ...interface{}) (n int, err error) {
274 return Fprintln(os.Stdout, a...)
275 }
a ...interface{}
はあらゆる引数を受け付ける可変長引数。可変長引数の実体はslice
らしい。
https://golang.org/ref/spec#Passing_arguments_to_..._parameters
標準出力os.Stdout
と受け取ったa...
を引数にしてFprintln
を呼び出している。
ここに与えられた引数に草を生やす関数Printlnw
を追加してみる。
277 // Printlnw formats using the default formats for its opedands and writes to standard output with weed.
278 func Printlnw(a ...interface{}) (n int, err error) {
279 b := append(a, "www")
280 return Fprintln(os.Stdout, b...)
281 }
append
はslice
にアイテムを追加して新しいslice
を生成する。
https://golang.org/pkg/builtin/#append
コンパイルしてみるとAPI Checkのあたりで失敗する。どうも公開する関数をapi/
ディレクトリにバージョン毎に定義しているらしのだが、詳細はちょっと調べたがよくわからなかった。
$ ./all.bash
(...省略)
##### API check
Error running API checker: exit status 1
Go version is "go1.14.2", ignoring -next /home/hidakanoko/Dev/go/goroot/api/next.txt
+pkg fmt, func Printlnw(...interface{}) (int, error)
exit status 1
2020/05/10 11:18:02 Failed: exit status 1
go tool dist: FAILED
しょうがないのでmake.bash
でビルドだけ実行。
$ ./make.bash
(...省略)
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /home/hidakanoko/Dev/go/goroot
Installed commands in /home/hidakanoko/Dev/go/goroot/bin
ビルド成功したので、テストプログラムを修正して実行してみる。
package main
import "fmt"
func main() {
fmt.Printlnw("hello, world")
}
コンパイルと実行。
$ go run ~/Dev/go/test/test.go
hello, world www
成功!!
Goの実行環境をDockerなどで用意する際は、こっそり草生やすバージョンと差し替えてメンバーの心をほっこりさせようと思う(怒られる)