The Gopher character is based on the Go mascot designed by Renée French
Future Tech Blog恒例のGoリリース連載が始まります。
Go 1.22のトピックとしては以下のようなものがあります。だいぶ安定版になってきたからか、言語もライブラリもこつぶなものが多くなってきたかな、という印象です。
- ループ変数の挙動の変化
- ツール系
- GO111MODULE=offオプションの廃止
- トレースツールのUI改善
- net/httpのServeMuxでパス変数が扱えるように
- go vet強化
- コンパイラでGCが1-3%高速化。PGOで2-14%改善
- リンカーの生成するバイナリがよりデバッガフレンドリーに
- ライブラリ
- math/rand/v2追加
- database/sql.NUllの追加
- net/httpのルーターがパスパラメータをとれるように
- その他
個人的に注目しているHTTP/3やQUICへの対応は、準標準ライブラリのgolang.org/x/net/internal/quicの中で進行中。将来的にはinternalが外れたgolang.org/x/net/quicができて、そののちに標準ライブラリ化される予定のようですが、まだ時間かかりそうですね。
https://github.com/golang/net/tree/master/internal/quic
2/1追記
database/sqlのNullの追加は以下のブログエントリーが詳しいです。コミットした本人によるブログ記事なので日本だけでなく海外含めてもこれよりも詳しい説明は存在しないでしょう。
methaneのブログ: sql.Null[T] をGo 1.22に追加しました
ループの変化(1)
Go 1.22は言語の変化としてはループ変数の扱いが変わったり、固定回数のループが描きやすくなったり、今後のバージョンで入る予定のrange over functionという機能が GOEXPERIMENT=rangefunc という環境変数のスイッチで有効になったりします。まずはループ変数の扱いの変化から説明します。
Goのループ変数は単なる参照でした。で、goroutineの起動には時間がかかります。次のようなコードを1.21までのGoで実行するとgoroutineが起動するころには呼び出し元のループは終わっていました。iは単なる参照で、iの最終の値は9なので、だいたい9が出力されます。
package main |
これに対処するために、わざわざ新しいメモリ領域が確保されるようにする必要がありました。主に2つの方法がありました。しかし、
// ループの中で変数を定義して代入 |
Go 1.22からは、ループ変数が内部のクロージャなどから参照されたりした場合はi := iを自動で差し込むようになり、呼び出したタイミングでのループ変数の値が中でも利用できます。
Goでgoroutineをループであつかう場合のよくある落とし穴が塞がれました。
ループの変化(2)
range over intというのが入りました。今まで、10回繰り返したい! みたいなループはC言語からの伝統のループを書く必要がありました。
// C言語からの伝統のループ |
これがこのように書けるようなります。
// 1.22からの新しいループ |
ループの変化(3)
Go 1.23以降に入る予定だが、1.22で実験的に実装されているものがrange over functionです。
古の書のデザインパターンを読んだことがある人もいるかもしれません。その中で「イテレーターパターン」というものがありました。繰り返し処理を自前で実装する方法を表現したものです。Goの標準ライブラリの中にもいくつかあります。イテレーターパターンはその実装方法から、内部と外部と2種類の分類が知られています
// 内部イテレータ |
だいたいの言語にはforループがあり、うまく外部イテレータを言語が定めるプロトコル通りに実装することで言語標準の文法の中で使えるような言語がいくつもあります。C++やJavaScriptのfor ofループや、Pythonの__iter__メソッドなどです。range over functionも、この仲間です。
使い方とかはすでに詳しくわかりやすく解説してくれているブログ記事があったりするのでそちらを見てもらえればよいかな、と思います。
これらがリリースされると、そのうち、次のように書けるようになるかと思います。まだExperimentalで変更もありえるので詳しくは説明しません。
// メソッド名は適当です |
TinyGo 0.31
Go本体のリリースしかあまり見てなかったのですが、以下のtakasagoさんの投稿を見て、TinyGoもリリースを予定していることを知りました。
Go 1.22 リリースに合わせて TinyGo 0.31 がリリースされる予定です。 Go 1.22 の encoding/json で新たに必要となった reflect.TypeFor の実装を足せばリリースできそうな感じ。
— takasago (@sago35tk) January 17, 2024
大きな変更として net package が TinyGo 内に用意され大幅に更新されました。このあたりは、別途。
ここ数年のGoのリリースと、それらのバージョンにあわせたTinyGoのバージョンを表にしたものが次の通りです。READMEの説明を見ると、昔は「完全ではない」という表現もあったりしたのですが、おおむね、2-3週間のラグで対応するバージョンが出ているようです。
せっかくなので、Go 1.22サポートを目指している開発版のTinyGoをインストールしてみます。手順はTinyGoのウェブサイトのBuild from sourceのページにあります。
$ git clone --recursive https://github.com/tinygo-org/tinygo.git |
さっそく実行してみようとすると、Go 1.22がないぞ、とのエラー。Go 1.22 rc 1をインストールして以下のrange over intのコードを動かしてみます。もう最新の言語サーバーのgoplsはrange over intを正しく解釈してくれるのですね。
package main |
以下のように実行すると、Go 1.22のコードをコンパイルして実行できました。小さいバイナリができてWASMでの利用もしやすいし、今後はちょくちょく触ってみようと思います。
$ tinygo run main.go |