🐷

「みんなのGo言語 第二版」補足。Go v1.16の新機能紹介など

2021/07/25に公開
2

はてなブログ上のこの記事からの転載。もともと技術の話だったからこっちに書けばよかった。

みんなのGo言語 第二版という本を読みました。とてもいい本でした。

この本が書かれた当時、2019年のGoの最新バージョンは本書の内容と発売時期から考えるとv1.12でした。それから二年の歳月が過ぎたいま、Goの最新バージョンはv1.16になっています。それにともなって本書のコンテンツのうちのいくつかは現在では違う方法が主流になっていたり、推奨されていたりします。本記事ではそれらについて紹介します。

最初に断っておきますが本書の内容が古いと文句をいいたいわけではなく、この書籍に最新のGoの状況を補足しておくと誰かの役に立つかもしれないと思っただけです。

P15: GO111MODULE環境変数

go v1.16からGO111MODULE環境変数の値はデフォルトでonになっています。Go v1.16のリリースノートからの引用です。

Module-aware mode is enabled by default, regardless of whether a go.mod file is present in the current working directory or a parent directory. More precisely, the GO111MODULE environment variable now defaults to on.

P15: vendoring

Go v1.13からgoのモジュールはデフォルトでGo module mirrorというところからダウンロードするようになったため、ダウンロードの所要時間はgithubなどのサイトからダウンロードするより高速になりました。これによってvendoringの嬉しさの一つは薄れてきています。

以下、リリースノートの該当部分からの引用です。

As of Go 1.13, the go command by default downloads and authenticates modules using the Go module mirror and Go checksum database run by Google. See https://proxy.golang.org/privacy for privacy information about these services and the go command documentation for configuration details including how to disable the use of these servers or use different ones. If you depend on non-public modules, see the documentation for configuring your environment.

go module mirrorをはじめとするGo module proxyとvendoringの比較についてはこのドキュメントをごらんください。

P16: 依存の追加

モジュールを有効にした場合(つまりデフォルト)のパッケージのビルド/インストール、および依存関係の更新において推奨されるコマンドが変更になりました。

  • パッケージのインストール: go install
  • 依存関係の更新: go get -d

-d引数なしのgo get、つまりパッケージをビルド/インストールする目的でのgo getの使用は非推奨となりました。以下Go v1.16のリリースノートからの引用です。

go install now accepts arguments with version suffixes (for example, go install example.com/cmd@v1.0.0). This causes go install to build and install packages in module-aware mode, ignoring the go.mod file in the current directory or any parent directory, if there is one. This is useful for installing executables without affecting the dependencies of the main module.

go install, with or without a version suffix (as described above), is now the recommended way to build and install packages in module mode. go get should be used with the -d flag to adjust the current module's dependencies without building packages, and use of go get to build and install packages is deprecated. In a future release, the -d flag will always be enabled.

P41 statikを使う

バイナリにファイルコンテンツを埋め込む方法としてstatikが定番でしたが、Go v1.16からはembedというパッケージを使えば同じことができるようになりました。

以下Go v1.16のリリースノートからの引用です。

The new embed package provides access to files embedded in the program during compilation using the new //go:embed directive.

embedは以下のように使います。

$ echo "hello embed!" >hello.txt
$ cat hello.txt 
hello embed
$ cat emb.go
package main

import (
	_ "embed"
	"fmt"
)

//go:embed hello.txt
var s string

func main() {
	fmt.Print(s)
}
$ go build emb.go
$ ./emb
hello embed!
$ 

詳しい使い方はライブラリのドキュメントをごらんください。

P63: ioutilパッケージ

リスト18において使われているioutilパッケージの使用はGo v1.16から非推奨になりました。以下リリースノートからの抜粋です。

The io/ioutil package has turned out to be a poorly defined and hard to understand collection of things. All functionality provided by the package has been moved to other packages. The io/ioutil package remains and will continue to work as before, but we encourage new code to use the new definitions in the io and os packages. Here is a list of the new locations of the names exported by io/ioutil:

Discard => io.Discard
NopCloser => io.NopCloser
ReadAll => io.ReadAll
ReadDir => os.ReadDir (note: returns a slice of os.DirEntry rather than a slice of fs.FileInfo)
ReadFile => os.ReadFile
TempDir => os.MkdirTemp
TempFile => os.CreateTemp
WriteFile => os.WriteFile

軽微な誤り

Goのバージョンには関係ないですが、本書の中に公式の正誤表に載っていない軽微な誤りが2点ありましたので書いておきます。出版社に連絡したので、いずれ正誤表に載るかもしれません。

P108 4つ目のcode snippet

xv := rv.Field(0)

rvはpへのポインタを指しているので、ここではElem()で実体にアクセスする必要があります。

xv := rv.Elem().Field(0)

P116 1つ目のcode snippet

if f := rv.Field(0); f.CanSet() {

一つ目の指摘と同じ理由により、以下のようにする必要があります。

if f := rv.Elem().Field(0); f.CanSet() {

おわりに

本記事の補足内容は私が本書の中のちゃんと読んだところについて自分の知ってる最新状況について補足しただけであって、すべて最新版のbest practiceに置き換えたようなものではないです。

最後になりますが「みんなのGo言語」の筆者のかたがたに、良書を書いてくださってありがとうございましたと感謝申し上げます。

Discussion

たふみたふみ

記事参考になりました,ありがとうございます!

軽微な修正提案が1つあります.ご確認いただけますと幸いです.

https://zenn.dev/satoru_takeuchi/articles/37674810946531#p108-4つ目のcode-snippet

ここについてですが,1つ目の例は

xv := rv.Elem().Field(0)

ではなく

xv := rv.Field(0)

ではないでしょうか.

satsat

ご指摘ありがとうございます。そのとおりです。ネタ元のはてなブログのエントリも含め、修正しました。