READMEにpkg.go.devのバッジを貼る
godoc.orgはpkg.go.devに移行していくことが告知されているので、新しいプロジェクトではREADME.mdに貼っているバッジを移行しましょう。pkg.go.devのURLやバッジは
// バッジ https://pkg.go.dev/badge/<package path> // リンク https://pkg.go.dev/<package path>
の形を取ります。例えばgithub.com/lufia/backoffの場合は以下のように書きます。
# Backoff ...summary... [![GoDev][godev-image]][godev-url] ...description... [godev-image]: https://pkg.go.dev/badge/github.com/lufia/backoff [godev-url]: https://pkg.go.dev/github.com/lufia/backoff
pkg.go.devのバージョンを更新する
GitHubなどで新しいタグをpushしても、何もしなければ(少なくとも数日は)モジュールインデックスに反映されません。すぐに更新したい場合、最新バージョンを明記してgo get
しておきましょう。
// アクセスすればいいので-dオプションをつけてもいい % go get github.com/lufia/backoff@v1.3.0
これで数時間後には反映されるはずです。モジュールの動作は以下の記事がとても詳しいので読んでおくとよくわかります。
Goバイナリのランタイムバージョンを調べる
runtime.Versionを使うと、Goでビルドされたコマンド自身は、どのバージョンでビルドされたのかを実行時に調べることができますが、ファイル名を指定して調べる方法は(少なくとも簡単に調べる方法は)提供されていませんでした。
// 自身のランタイムバージョンしか取れない fmt.Println("Version:", runtime.Version())
Go 1.13から、go version
コマンドに-m
オプションが追加されました。このコマンドに実行ファイルを渡すと、どのバージョンでビルドされたのかを調べられるようになりました。モジュールが使われている場合は、モジュールのバージョンも調べられます。また、ディレクトリを渡した場合は、ディレクトリに含まれるたGoバイナリ全てを調べます。
% go version -m ~/bin/act /Users/lufia/bin/act: go1.14.6 path github.com/nektos/act mod github.com/nektos/act v0.2.10 h1:aMSXUGybVyLIqe3ak9GyCtRVpBxwAiSBR5stqas0lj0= dep github.com/MichaelTJones/walk v0.0.0-20161122175330-4748e29d5718 h1:FSsoaa1q4jAaeiAUxf9H0PgFP7eA/UL6c3PdJH+nMN4= dep github.com/andreaskoch/go-fswatch v1.0.0 h1:la8nP/HiaFCxP2IM6NZNUCoxgLWuyNFgH0RligBbnJU= dep github.com/containerd/containerd v1.3.3 h1:LoIzb5y9x5l8VKAlyrbusNPXqBY0+kviRloxFUMFwKc= dep github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= dep github.com/docker/cli v0.0.0-20190822175708-578ab52ece34 h1:H/dVI9lW9zuagcDsmBz2cj8E8paBX5FarjO7oQCpbVA= dep github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= dep github.com/docker/docker v0.0.0-20200229013735-71373c6105e3 h1:hq9QaRK9JJOg7GItpuSSA3MrBoEN3c3llxQappEq9Zo= ...
1.13より前のバージョンでビルドしたコマンドは、ランタイムのバージョンだけならgoversionで調べられます。こちらもgo version
と同様に、ディレクトリを渡せます。
% go get github.com/rsc/goversion % goversion ~/bin
チャネルのスライスでselectする
動的に増減する複数のチャネルを使って、どれでもいいので送信可能になったチャネルへデータを送る、または受信可能なデータを取り出す動作を実装したい場合にreflect.Selectが使えます。以下の例は受信しか行っていませんが、だいたいの使い方はこんな雰囲気。
package main import ( "fmt" "math/rand" "reflect" "time" ) func main() { rand.Seed(time.Now().UnixNano()) a := make([]chan int, 5) for i := 0; i < len(a); i++ { a[i] = make(chan int) } cases := make([]reflect.SelectCase, len(a)) for i, c := range a { cases[i] = reflect.SelectCase{ Dir: reflect.SelectRecv, Chan: reflect.ValueOf(c), } } const N = 10 go func() { for i := 0; i < N; i++ { off := rand.Int() % len(a) a[off] <- i } }() for i := 0; i < N; i++ { // casesに含まれるチャネルのどれかにデータが届いたらSelectを抜ける off, v, ok := reflect.Select(cases) fmt.Println(off, v, ok) } }
ところで、Goの前身となる言語にはこういった機能が言語仕様に盛り込まれていたのですが、Goでは意図的に外されたようです。なので回避できるなら使わない方が良いのかもしれません。代わりに、例えばchan chan int
のようにチャネルを送受信するチャネルを使うと、同じようなことはできます。
runtime.GOOSとbuild constraintsのどっちを使う
golang-nutsより。
all.bashのタイムアウト
Goをソースからコンパイルするときテストを実行しますが、このテストは10分弱でタイムアウトします。マシン性能が悪くタイムアウトしてしまう場合、環境変数GO_TEST_TIMEOUT_SCALEに2を設定すると、タイムアウトが標準の2倍になります。Plan 9でのテストは一部とても遅いものがあるので、この設定が必要です。
presentスライド
Go関連の発表でよく使われる、テキストを書くとスライドにしてくれるpresentというツール*1があるのですが、以前は独特な記法で書く必要がありました。最近この記法が、Markdownに似たものに変更されたようです。
とはいえ、今も古い記法に対応していて、どっちの記法を使うのかは、テキスト中に#
(スペースを含む)が1つでもあればMarkdown風の記法が使われます。
ただし、talks.godoc.orgはまだ新しい記法に対応していません。