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

[golang/go](https://github.com/golang/go) の master ブランチに行われたコミットから個人的に気になったものをリストにしたものです。

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

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

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

## Topic

- BoringCrypto を使うための `dev.boringcrypto` ブランチが master にマージされました。 :tada:
- 環境変数 `GOMEMLIMIT` でメモリ使用量のソフトリミットを設定できるようになりました。
- 標準パッケージにジェネリクスが導入されました。

## Commits

### 2022-05-02

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

ファイルディスクリプタに対する書き込み処理にて内部で保持している使用済みバッファが GC に回収されやすくなるように修正されています。
Go 1.17 で [`net.Buffers`](https://pkg.go.dev/net#Buffers) に入っていたのと同様の処理を適用したようです。 [^1]

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

### 2022-05-03

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

BoringCrypto を使うための `dev.boringcrypto` ブランチが master にマージされました。
デフォルトでは無効化されていますがビルドタグで `boringcrypto` を指定すると有効になるようです。 [^2]

[^2]: https://github.com/golang/go/issues/51940#issuecomment-1146667386

https://github.com/golang/go/commit/0668e3cb1a8407547f1b4e316748d3b898564f8e

for range ループでスライスをゼロクリアする際に Go コンパイラはランタイム関数 `memclrNoHeapPointers()` を使用して最適化しますが、 range にスライスのポインタを渡した場合に最適化が実行されない問題が修正されています。 [^3]

[^3]: https://github.com/golang/go/issues/52635

### 2022-05-04

https://github.com/golang/go/commit/01359b46815e63307077dfa03972f40d2e0d94fe

GC による CPU 使用率が 50%を超えないようにするリミッターが追加されました。

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

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

https://github.com/golang/go/commit/85d466493dc5b46228440fcb3dafacf4556101e6

https://github.com/golang/go/commit/4649a439035a0634109f11f7ac25e4e7184b5598

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

https://github.com/golang/go/commit/375d696ddf102d64729a21f931f4e1d8bfa82ce5

https://github.com/golang/go/commit/473c99643f3da2b02949554a66d8582c926ed725

https://github.com/golang/go/commit/129dcb7226678d8ccd06c016de3fcfcc43b9aa9c

https://github.com/golang/go/commit/973dcbb87c0097c783abe35e319725c68167f718

https://github.com/golang/go/commit/7e4bc74119a431f3f0dd3dadd05bbb045969190d

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

https://github.com/golang/go/commit/91f863013e6b5ba870f6bfbfda0b735cf54fb3ca

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

環境変数 `GOMEMLIMIT` でメモリ使用量のソフトリミットを設定できるようになりました。 [^4]
ソフトリミットは `runtime/debug.SetMemoryLimit()` でも設定できるようです。
また、 GC アルゴリズムもソフトリミットを考慮した形に修正されています。

[^4]: https://github.com/golang/go/issues/48409

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

https://github.com/golang/go/commit/52bd1c4d6cc691aa60c71513695dba03062deb59

大量の goroutine が動いている環境で goroutine profile を取得するとレイテンシースパイクが発生する問題が改善されています。 [^5]
取得に要する時間は増加してしまいますが STW を減らしたようです。

[^5]: https://github.com/golang/go/issues/33250

https://github.com/golang/go/commit/89c0dd829f49c91eb2636bc2b24df0b1cdc74a1c

メモリ管理のための領域に対するロックを分割することで GC での STW を減らすための修正です。 [^6]

[^6]: https://github.com/golang/go/issues/45894

### 2022-05-05

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

[`sync/atomic`](https://pkg.go.dev/sync/atomic) に型付きの値が追加されました。 [^7]
`Bool`, `Int32`, `Int64`, `Uint32`, `Uint64`, `Uintptr` のほかにジェネリクスを使用した任意の型のポインタ `Pointer[T any]` が追加されています。
標準パッケージに対するジェネリクス追加はこれが初めてではないかと思います。

[^7]: https://github.com/golang/go/issues/50860

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

[`io.LimitedReader`](https://pkg.go.dev/io#LimitedReader) に Err フィールドが追加されました。 [^8]
従来は制限値に到達した際に返すエラーは `io.EOF` 固定でしたがこの変更により呼び出し元で任意のエラーを指定できるようになりました。
ただし、この変更については実際のデータ量と制限値が同じだった場合に `io.EOF` 以外のエラーを返す動作が議論の対象となり revert されました。

[^8]: https://github.com/golang/go/issues/51115

### 2022-05-07

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

TLS コネクション確立時の Handshake で行われるメモリ割り当て回数を削減しています。

### 2022-05-10

https://github.com/golang/go/commit/53f13128a7a4c7d16af5ea9ca5f25b56ff9881fe

riscv64 でレジスタベースの関数呼び出し規約がデフォルトで有効になりました。
amd64, arm64, ppc64 に続くアーキテクチャになります。

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

連続したメモリをゼロクリアするためのランタイム関数 `memclrNoHeapPointers()` が最適化されています。
ERMSB が利用可能かつサイズ大きい場合は AVX2 より速いようです。

### 2022-05-17

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

`time.Time` に `ZoneBounds()` というメソッドが追加されています。 [^9]
夏時間などの移行タイミングを想定しているらしくタイムゾーンの開始・終了時刻を取得できるようです。

[^9]: https://github.com/golang/go/issues/50062

### 2022-05-18

https://github.com/golang/go/commit/770e0e584a98dfd5e8d0d00558085c339fda0ed7

ステータスコード 1xx に対応するための修正です。
[`http.ResponseWriter`](https://pkg.go.dev/net/http#ResponseWriter) の `WriteHeader()` は複数回の呼び出しが認められていませんでしたが 100 から 199 のステータスについてはカウントされなくなったうえに書き込み中のバッファが flush されるようになりました。 [^10] [^11] [^12]

[^10]: https://github.com/golang/go/issues/26088
[^11]: https://github.com/golang/go/issues/26089
[^12]: https://github.com/golang/go/issues/36734

https://github.com/golang/go/commit/668041ef66ddafffccf1863e6180b83ea1ad30c9

バイトスライスに文字列を追加するための `Append()`, `Appendf()`, `Appendln()` が [`fmt`](https://pkg.go.dev/fmt) パッケージに追加されています。 [^13]

[^13]: https://github.com/golang/go/issues/47579

### 2022-05-19

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

新しいアーキテクチャ linux/loong64 への移植が完了しました。 [^14]

[^14]: https://github.com/golang/go/issues/46229

## 雑感

引き続き多数の改善が行われています。
その一方で Go 1.19 ベータが近づいておりリリースノート周りの修正も目立つようになってきました。