Go の気になったコミット (2022 年 3 月)

[golang/go](https://github.com/golang/go) の master ブランチに行われたコミットから個人的に気になったものをリストにしたものです。
タイトルに 2022 年 3 月と銘打っていますが 2 月のコミットも含まれています。

前回作成したリストはこちら。

https://qiita.com/sg0hsmt/items/f726dc783f4382897d47

軽く説明を追加していますが勘違いや誤りがあるかもしれません。

## Topic

https://go.dev/blog/go1.18

- Go 1.18 がリリースされました。 :rocket:
- Go 1.19 の開発がスタートしました。 :rocket:

## Commits

### 2022-02-10

https://github.com/golang/go/commit/9cec77ac11b012283e654b423cf85cf9976bedd9

Go 1.18 で追加される `debug.BuildInfo` が提供する関数が変更されました。

https://github.com/golang/go/commit/2e9dcb508647dc473a37ecfa244d2bc4a1843ab4

runtime 内で使用されている時間分布のヒストグラム処理でバケットの計算に誤りがあったようです。 [^1]
この修正は Go 1.16.15 および Go 1.17.8 にもバックポートされています。

[^1]: https://github.com/golang/go/issues/50732

### 2022-02-11

https://github.com/golang/go/commit/452f24ae94f38afa3704d4361d91d51218405c0a

スタックオーバーフローを避けるため、ネストされた正規表現に深さ制限 (1000) が追加されました。 [^2]
この修正は Go 1.16.15 および Go 1.17.8 にもバックポートされています。

なお、その後の修正により Go 1.19 では新しいエラーが定義されています。 [^3]

[^2]: https://github.com/golang/go/issues/51112
[^3]: https://github.com/golang/go/commit/1af60b2f4990bffdd1b050ffd11e978578d1e38f

### 2022-02-16

https://github.com/golang/go/commit/6e82ff83cfbef78aa60706c1a7167a31c30e7ef9

DNS のレスポンスサイズが 512 byte を超えている場合に `cannot unmarshal DNS` というエラーが出ていたのをバッファサイズを 1232 byte に増やすことで回避しています。 [^4]
RFC 的には 512 byte に制限していても問題ないですが実環境で多数の問題が発生しているためサイズを大きくしたようです。 [^5] [^6] [^7] [^8]
この修正は Go 1.16.15 および Go 1.17.8 にもバックポートされています。

当初は EDNS(0) をデフォルトで有効化するような形で実装されましたが互換性を考慮して単にバッファサイズ変更のみ行うように再修正、 EDNS(0) のデフォルト有効化は Go 1.19 向けにリスケジュールしています。 [^9]

[^4]: https://github.com/golang/go/issues/51153
[^5]: https://github.com/golang/go/issues/6464
[^6]: https://github.com/golang/go/issues/21160
[^7]: https://github.com/golang/go/issues/44135
[^8]: https://github.com/golang/go/issues/51127
[^9]: https://github.com/golang/go/commit/301fd8ac8b6cd93708ad536eb054e1b081982a9b

### 2022-02-25

https://github.com/golang/go/commit/6d810241ebd2a02bc63b7706ad68ae8d0edbfd8e

Linux カーネルの要求バージョンが 2.6.32 以上になりました。 [^10]
これにより古いカーネルをサポートするための処理が削除できるようになりました。 [^11] [^12]

[^10]: https://github.com/golang/go/issues/45964
[^11]: https://github.com/golang/go/commit/6c6a8fb702fcf3c2d23dc68976a831b2bdcad03e
[^12]: https://github.com/golang/go/commit/9d34fc5108d91bfcce3c465069dbb2c563af4229

### 2022-03-01

https://github.com/golang/go/commit/936c7fbc1c154964b6e3e8a7523bdf0c29b4e1b3

バージョンが Go 1.18 から Go 1.19 に変更されました。 :rocket:

なお、この時点では Go 1.18 の開発が継続中だったうえに Go 1.18 のリリースブランチは Go 1.18 rc.1 時点のものでした。
このためバージョンを Go 1.19 に変更する直前までの変更を Go 1.18 のリリースブランチに取り込んだ [^13] のち、それ以降に行われた変更は master ブランチに行われた変更から Go 1.18 にも必要なものを個別に取り込む形になっています。 [^14] [^15]

[^13]: https://go-review.googlesource.com/c/go/+/389554/
[^14]: https://github.com/golang/go/issues/51336
[^15]: https://github.com/golang/go/issues/51460

### 2022-03-02

https://github.com/golang/go/commit/302af4be8e27b55b7a8572adece64e2271d09b97

https://github.com/golang/go/commit/ad523565369af0005c59232e5d2dd7359073f0f4

https://github.com/golang/go/commit/0fcb94895fa3efd9733e5ab66f5634f92cee9aa3

https://github.com/golang/go/commit/d6d2ebb7b8194eb20d95b84bae39f7a5837e9f72

ジェネリクス非対応の旧コードが削除され `-G` オプションが廃止されました。

https://github.com/golang/go/commit/aaa3d39f270d7b9957f34f3d2a68decba63beffe

map リテラルで map を作成する際の初期キャパシティが小さく、項目数が 9 以上の場合にキャパシティ拡張が発生する問題が修正されました。 [^16]
今後は宣言された項目を格納するのに十分なキャパシティが最初から確保されるようになります。

[^16]: https://github.com/golang/go/issues/43020

https://github.com/golang/go/commit/bebe9aa42322f951fc3972c263648297bf9e04d4

Go のトークン解析パフォーマンスが少し向上するようです。

https://github.com/golang/go/commit/fd2e1e743a86a53a30427cf3606543ecc9bd60bd

[`utf8.Valid()`](https://pkg.go.dev/unicode/utf8#Valid) のパフォーマンスが向上しています。
スライス容量の再計算を省くための最適化をしているとのことです。

### 2022-03-03

https://github.com/golang/go/commit/986b04c0f12efa1c57293f147a9e734ec71f0363

[`encoding/binary`](https://pkg.go.dev/encoding/binary) に固定長の整数値を byte スライスに追加する関数が追加されました。 [^17]
Issue にも書かれていますがバイナリデータを出力する操作が簡単になりそうです。

[^17]: https://github.com/golang/go/issues/50601

https://github.com/golang/go/commit/da6f9a54edb85365bb345b057cdc26e2527401c8

ジェネリクス対応を想定して sort パッケージのコード生成処理が変更されています。 [^16]

[^16]: https://github.com/golang/go/issues/47619

### 2022-03-04

https://github.com/golang/go/commit/87a345ca3849a68de13f29bdc7628f2943734946

Go 1.18 で追加された go.work ですが `go work init .` で初期化すると `.` ではなく `./.` が設定される不具合が修正されています。 [^18]

[^18]: https://github.com/golang/go/issues/51448

### 2022-03-08

https://github.com/golang/go/commit/079a027d27a9eed18c99c0c6a6e2fc70f9dd07b7

[`io.MultiReader`](https://pkg.go.dev/io#MultiReader) でゼロコピーを実現するための修正が行われています。 [^19]

[^19]: https://github.com/golang/go/issues/50842

### 2022-03-09

https://github.com/golang/go/commit/0b76afc75ca687fcd9a1a8e0b19670fb8f37fecb

`crypto/rand` の `Prime()` が簡素化されました。
incremental search を廃止して rejection sampling のみにしたとのことです。
タイミングリークしにくくなるなどのメリットがあるようです。

### 2022-03-10

https://github.com/golang/go/commit/604140d93111f89911e17cb147dcf6a02d2700d0

[`net/url`](https://pkg.go.dev/net/url) にパス操作用の関数として `JoinPath()` が追加されました。 [^20]

[^20]: https://github.com/golang/go/issues/47005

### 2022-03-11

https://github.com/golang/go/commit/2d026a4ea5b28680c1ed7660f720c4cb028c5b35

[`bytes.Buffer`](https://pkg.go.dev/bytes#Buffer) の内部バッファを拡張する際のサイズが変更されました。 [^21]
具体的には `2*cap+n` だったのが `len+n` と `2*cap` の大きい方に変更されており、メモリ消費を削減しつつ大幅に高速化しています。

[^21]: https://github.com/golang/go/issues/42984

### 2022-03-12

https://github.com/golang/go/commit/baf61e4a67789e20f019507287a324cca06bed42

[`encoding/hex`](https://pkg.go.dev/encoding/hex) をテーブルベースの実装に変更することで大幅に高速化しています。
変換テーブルが追加されているにもかかわらず関数の簡略化や削除によって amd64 だとバイナリサイズも小さくなるようです。

### 2022-03-13

https://github.com/golang/go/commit/842d37ee5f86f12aa096b750adbd2debd9129fcb

[`os.File.ReadAt()`](https://pkg.go.dev/os#File.ReadAt) に対するレースコンディションを検出できない不具合が修正されています。
このコミットだけでは修正が不十分だったため追加のコミットも行われています。 [^22] [^23] [^24]

[^22]: https://github.com/golang/go/commit/e475cf2e705d4eda8647426e060898ab3f643610
[^23]: https://github.com/golang/sys/commit/27bbf83dae8796c63b8dd88064c11bea9a730daa
[^24]: https://github.com/golang/sys/commit/039c03cc5b867cd7b06a19ff375be5c945c80b10

### 2022-03-14

https://github.com/golang/go/commit/ab0f7611d739fe10d0265dbc6bdc17684423bfc8

[`net/url`](https://pkg.go.dev/net/url) の URL にホスト名が設定されていないことを示す `URL.OmitHost` フィールドが追加されました。 [^25]
スキーマ名とパスのみの URL を処理する際に便利そうです。

[^25]: https://github.com/golang/go/issues/46059

### 2022-03-15

https://github.com/golang/go/commit/b7041c7ad1c9d42078cfc376320e5b307e617a80

次のバージョン向けに新規追加された API は `api/next.txt` に記録されていたのが廃止され、 `api/next/#nnnnn.txt` というファイル (`#nnnnn` は GitHub Issue 番号) で記録するようになりました。
リリース時に連結されて `go1.XX.txt` というファイルに保存されます。

https://github.com/golang/go/commit/41a82aa9c36bffab2593d50aa55a462fef4e5bd4

`text/template` などで Go 1.18 から利用可能になった continue と break について、前後に空白があるとエラーになる不具合が修正されました。 [^26]
Issue には `CherryPickCandidate` ラベルが設定されていますが現時点で Go 1.18 へのバックポートはされていません。

[^26]: https://github.com/golang/go/issues/51670

### 2022-03-17

https://github.com/golang/go/commit/e5e638e512e1ec27673d5e01e99eb870899be7f7

Go には map の全エントリーを削除するような for ループを検出して mapclear と呼ばれる専用処理に置き換える最適化処理がありますが、ジェネリクス使用時は最適化されない問題が修正されました。 [^27]

[^27]: https://github.com/golang/go/issues/51699

### 2022-03-26

https://github.com/golang/go/commit/1d19cea740a5a044848aaab3dc119f60c947be1d

[`net/http/httptest`](https://pkg.go.dev/net/http/httptest) で発生するレースコンディションが修正されました。 [^28]
Go 1.18 向けにバックポート予定みたいですがまだされていません。

[^28]: https://github.com/golang/go/issues/51799

https://github.com/golang/go/commit/80a7504a13a5dccb60757d1fc66d71bcba359799

select が含まれる関数もインライン化できるようになりました。

### 2022-03-28

https://github.com/golang/go/commit/0bbd05b8262624bb8e8aea43fa76934fbff8fc81

[`time.Duration`](https://pkg.go.dev/time#Duration) に絶対値を返す `Duration.Abs()` が追加されました。 [^29]
2 つの `time.Time` の差が一定時間内ならとかの処理を書きやすくなります。

これより先に 2 つの `time.Time` の大小比較を行う `Time.Compare()` が提案されており受け入れられているのですがこちらはまだ実装されていないようです。 [^30]

[^29]: https://github.com/golang/go/issues/51414
[^30]: https://github.com/golang/go/issues/50770

### 2022-03-29

https://github.com/golang/go/commit/a208aa7f339db75f4b79a61be12616b846477a18

Go 1.16 で非推奨になった `io/ioutil` に `Deprecated:` コメントが追加されました。 [^31] [^32]
これによってドキュメントに非推奨マーカーが表示され Linter での検出も容易になるそうです。

[^31]: https://go.dev/doc/go1.16#ioutil
[^32]: https://github.com/golang/go/issues/51927

https://github.com/golang/go/commit/32fdad19a246143ae4f194d1b39886d778de1380

[`bytes.Trim()`](https://pkg.go.dev/bytes#Trim) および [`bytes.TrimLeft()`](https://pkg.go.dev/bytes#TrimLeft) に空スライスを渡した場合は空スライスではなく nil を返すように修正されました。 [^33]
これは Go 1.17 以前の動作に合わせたものです。

Go 1.18 にもバックポートされていますがまだリリースはされていません。 [^34]

[^33]: https://github.com/golang/go/issues/51793
[^34]: https://github.com/golang/go/commit/8b0583a05441b84a99d03daa78a24306c85cddd3

https://github.com/golang/go/commit/c3fcd0117784ac05e35120ac0de6c960b400a31e

`unix` ビルドタグ指定時は UNIX ライクな GOOS とマッチするようになりました。 [^35]
当初は `_unix.go` というファイル名も対象にしようとしていたようですがビルドが広範囲で壊れたためファイル名による判定は見送りとなりました。

[^35]: https://github.com/golang/go/issues/51572

## 雑感

新しいリリースサイクルがスタートしたため多数の変更が行われています。
とはいえ Go 1.18 リリース前に Go 1.19 開発が始まったのはちょっと驚きでした。

またジェネリクス関連の修正も多数行われています。