フューチャー技術ブログ

Go 1.19リリース連載始まります GoDoc/ツール周りのアップデート

Go 1.18のジェネリクス導入の大規模リリースと比べると比較的小さな1.19ですが、それでもさまざまな変更があります。今回ももちろん、恒例行事になりつつある、このテックブログでリリース連載をやります。特に、網羅性とか考えずに書きたい人が書きたいテーマをピックアップしています。もし、「このテーマについて語らせろ!」という方がいましたら、社外からも飛び込み参加可能ですので、ぜひどうぞ。

なお、正式リリースはおそらく8月中旬になるかと思います。現時点の最新版のリリースノートを参考にしているため、もしかしたら正式版で変更があるかもしれません。その場合は補足を行う予定です。

Date Title Author
8/1 (月) Docコメント/ツール周りのアップデート 澁川喜規
8/2 (火) encoding/csv 真野隼記さん
8/3 (水) encoding/byte, fmtのAppend系メソッド 宮永崇史さん
8/4 (木) net/http 辻大志郎さん
8/5 (金) ジェネリクス 村上知優さん
8/8 (月) メモリ周り 澁川喜規

まずは、GoDocと、その他ツール周りのアップデートの紹介です。

Docコメントの更新

以前、Qiitaの方に、チョットできるGoプログラマーになるための詳解GoDocという記事を掲載しました。

https://qiita.com/shibukawa/items/8c70fdd1972fad76a5ce

GoDocの書き方の詳細ですが、以前は空行をあけて段落、インデントをしてフォーマット済みテキスト、URLがあればリンク、という程度のマークアップしかなく、とてもシンプルでした。GitHub FlavorなMarkdownとまでもいかなくても、もうちょっとマークアップが高機能になってほしい、せめてリストだけでも・・・と思っていた日本全国1億2000万のGoプログラマーにとって待望のアップデートが1.19で入りました。

  • セクションタイトル
  • リンク
  • リスト

また、gofmtが改善され、Docコメントでよくある間違いがチェックされるようになりました。詳しくはGo Doc Commentsというドキュメントを参照してください。

Docコメントはpkg.go.devで公開されるだけではなく、IDEでマウスオーバーしたときに表示されたりもするため、丁寧なドキュメントは利用者への助けとなります。

セクションタイトル(heading)

セクションタイトルはMarkdownと同じく、 # 記号+スペース+テキストという形式で書きます。なお、他のマークアップでは、HTMLにあわせてか、6階層まで書けるのですが、Goの場合は1階層のタイトルしか書けません。

// Package strconv implements conversions to and from string representations
// of basic data types.
//
// # Numeric Conversions
//
// The most common numeric conversions are [Atoi] (string to int) and [Itoa] (int to string).

リンクの書き方

まずリンクですが、URLを設定したい場合は、次のような [ ] でくくったテキストを書き、その下の注釈のようにリンクを書きます。書籍に書くような書き方ですね。あるいはreStructuredTextの、あまり使われない方の書き方。リンク定義のブロックは通常のパラグラフと空行で空けて書きます。gofmtはリンク定義のブロックは全自動で末尾に移動してくれるとのこと。

// Package json implements encoding and decoding of JSON as defined in
// [RFC 7159]. The mapping between JSON and Go values is described
// in the documentation for the Marshal and Unmarshal functions.
//
// For an introduction to this package, see the article
// “[JSON and Go].”
//
// [RFC 7159]: https://tools.ietf.org/html/rfc7159
// [JSON and Go]: https://golang.org/doc/articles/json_and_go.htmlpackage json

それ以外に、リファレンスの中で相互リンクも書けるようになります。パッケージ名(階層があるならencoding/jsonのようにスラッシュ付きで)、構造体のようなトップの要素、それらの子供の要素などをピリオドでつないで書くとのこと。オプションでアスタリスクを前につけて、 [*bytes.Buffer]のようにもできるとのことです。

// ReadFrom reads data from r until EOF and appends it to the buffer, growing
// the buffer as needed. The return value n is the number of bytes read. Any
// error except [io.EOF] encountered during the read is also returned. If the
// buffer becomes too large, ReadFrom will panic with [ErrTooLarge].

リスト

リストは、今までのコードブロックの派生という感じで、リストの前の段落の末尾のコロンと、リストのインデントが必要な点に要注意です。

バレットリストと数字つきの2つがあります。バレットリストはマイナス記号やアスタリスクなど複数の記号に対応しているとのことですが、gofmtにかけると、空白スペース2個+マイナス+スペースに整列しちゃうとのことで、マイナスだけ覚えておけば良さそう。

数字は他のマークアップでもよくある形式ですが、スペースが前に1個入るのが正式とのこと(gofmtがそのように整形する)。

ただし、ネストなどはできませんし、リストの中にコードブロックなども書けません。

// PublicSuffixList provides the public suffix of a domain. For example:
// - the public suffix of "example.com" is "com",
// - the public suffix of "foo1.foo2.foo3.co.uk" is "co.uk", and
// - the public suffix of "bar.pvt.k12.ma.us" is "pvt.k12.ma.us".
//
// Clean returns the shortest path name equivalent to path
// by purely lexical processing. It applies the following rules
// iteratively until no further processing can be done:
//
// 1. Replace multiple slashes with a single slash.
// 2. Eliminate each . path name element (the current directory).
// 3. Eliminate each inner .. path name element (the parent directory)
// along with the non-.. element that precedes it.
// 4. Eliminate .. elements that begin a rooted path:
// that is, replace "/.." by "/" at the beginning of a path.

コードブロック

これは前からあったものです。前の段落の末尾のコロン+インデントで、スペースなどが維持された形で表示されます。

// Search uses binary search...
//
// As a more whimsical example, this program guesses your number:
//
// func GuessingGame() {
// var s string
// fmt.Printf("Pick an integer from 0 to 100.\n")
// answer := sort.Search(100, func(i int) bool {
// fmt.Printf("Is your number <= %d? ", i)
// fmt.Scanf("%s", &s)
// return s != "" && s[0] == 'y'
// })
// fmt.Printf("Your number is %d.\n", answer)
// }

Go Doc Commentsドキュメントは必読

今回はメモリやGCに加えて、Doc Commentsのドキュメントが追加されました。上記のサンプルはここからの引用でした。

なお、このドキュメントは単に文法の書き方だけではなく、パッケージ、コマンド、型、関数、定数、変数といった要素へのドキュメントの書き方のベストプラクティスが前半の半分を占めています。

例えば、ゼロ値が目的を持っている場合は書け、とか関数の場合は名前付きの返り値との併用で読みやすくなるぞ、とか、並列実行でユーザーの期待と違う場合(型の場合はデフォルト並列不可、関数の場合は並列可能、というのが期待のライン)はきちんと明示的に説明しよう、とかですね。

この前半部分、Go特有の内容もありますが、JavaとかTypeScriptとか使っている人にも役立つと思うので、社内で勉強会をしているのであれば、軽くみんなで読む教材として取り上げてもよいかと思います。

また、最後にはよくある間違いについての説明もあります。

その他のツールの更新

その他気になる改善としては、コンパイラの更新がいくつかありました。

unix というbuild constraintが追加

Go 1.17でsignal_unix.goは次のようなbuild constraintがついていました。

os/signal/signal_unix.go
//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || windows

それがこんなにコンパクトになりますよっと。いいですね。

os/signal/signal_unix.go
//go:build unix || (js && wasm) || windows

コンパイラの改良でswitch文が高速化

数値と文字列を対象にジャンプテーブルを使うように改良されたため、20%ほど高速化されたとのことです。

ELF環境でリンカーが圧縮形式のデバッグ情報を持つようになった

レガシーな.zdebugから、SHF_COMPRESSEDに変わったとのことでした。Hello Worldの短いプログラムを作ってサイズを比較してみました(M2 Air上でGOOS=linux go build)。

1.18 1.19rc2
1799875 1821715

うーむ。増えてる?とはいえ、Mach-OなmacOSネイティブでやった場合はもうちょっと(70KB)増えていたので他の増加分が打ち消された、と考えれば良さそう。