Slide 1

Slide 1 text

What's new in Go 1.20? syumai Go 1.20 Release Party (2023/2/21)

Slide 2

Slide 2 text

自己紹介 syumai Go Documentation 輪読会 / ECMAScript 仕様輪 読会 主催 株式会社ベースマキナで管理画面のSaaS を開発中 Go でGraphQL サーバー (gqlgen) や TypeScript で フロントエンドを書いています Twitter: @__syumai Website: https://syum.ai

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

言語仕様の変更

Slide 5

Slide 5 text

スライスから配列への変換 Go 1.17 でスライスを配列のポインタに変換出来るようになった スライスを配列に変換したい時は、まず配列のポインタに変換した 上でデリファレンスする必要があった Go 1.20 では、スライスを直接配列に変換出来るようになった s := []int{1, 2, 3} a1 := *(*[3]int)(s) // Go 1.17 までの書き方 a2 := [3]int(s) // Go 1.20 からの書き方 a3 := [2]int(s) // OK: 変換後の配列の方が変換前のスライスより短い a4 := [4]int(s) // NG: 変換後の配列の方が変換前のスライスより長い (panic) https://go.dev/play/p/Mqt9E7iYqfT

Slide 6

Slide 6 text

unsafe package への変更 SliceData / StringData 関数の追加 slice / string から、基底配列の開始位置へのポインタを取得する String 関数の追加 基底配列の開始位置へのポインタと、長さから文字列を生成する // String 関数の例 b := []byte("abc") s := unsafe.String(&b[0], 3) // byte へのポインタと長さから文字列を生成 fmt.Println(s) // abc b[2] = byte('a') fmt.Println(s) // aba => byte slice から作った文字列を後から変更可能 https://go.dev/play/p/WrcSLoRYA-n

Slide 7

Slide 7 text

複合型の値の比較についての仕様の明確化 構造体の値同士の比較は、構造体型の定義に現れるフィールドの順で 行われ、最初に一致しなかった箇所で止まることが明記された 配列型についても同様の内容が明記された いずれの仕様も、比較時にどのタイミングでpanic するかを明確化す るもの 既存のコードを変更する必要はない

Slide 8

Slide 8 text

comparable 制約の変更 比較可能な型(comparable types) が、comparable 制約を満たすように なった。 これまでは、基本的なインタフェース(basic interface) 型のような、比 較可能だが実行時にpanic する可能性のある型はcomparable 制約を満 たさない仕様となっていた。 type StringMap[T comparable] map[T]string var m StringMap[any] // any はcomparable 制約を満たすのでOK " 満たす"(satisfy) と" 実装する"(implements) の定義が異なる点に注意 詳細についてはNobishii さんの記事の解説を参照ください https://zenn.dev/nobishii/articles/basic-interface-is-comparable

Slide 9

Slide 9 text

Ports

Slide 10

Slide 10 text

Windows Windows 7, 8, Server 2008 / Server 2012 で動くのはGo 1.20 が最後 Go 1.21 からはWindows 10 / Server 2016 以上が必要 Darwin and iOS macOS 10.13 High Sierra / 10.14 Mojave で動くのはGo 1.20 が最後 Go 1.21 からはmacOS 10.15 Catalina 以上が必要

Slide 11

Slide 11 text

FreeBSD/RISC-V RISC-V 上でのFreeBSD の試験的なサポートが追加 (GOOS=freebsd, GOARCH=riscv64)

Slide 12

Slide 12 text

Tools

Slide 13

Slide 13 text

Go command $GOROOT/pkg ディレクトリに、標準ライブラリの事前コンパイルさ れたパッケージアーカイブが保存されないようになった 代わりに、他のpackage 同様、必要に応じてビルドされた上でビル ドキャッシュが残るようになった go サブコマンドへの -C の追加 コマンド実行前にディレクトリが に変更される

Slide 14

Slide 14 text

Go command amd64.v2 などのアーキテクチャフィーチャービルドタグが追加 各アーキテクチャに対して、より細かいレベルでファイルをビルド に含めるかどうか選択可能になった go help buildconstraint の内容 ( 抜粋) The defined architecture feature build tags are: - For GOARCH=386, GO386=387 and GO386=sse2 set the 386.387 and 386.sse2 build tags, respectively. - For GOARCH=amd64, GOAMD64=v1, v2, and v3 correspond to the amd64.v1, amd64.v2, and amd64.v3 feature build tags. - For GOARCH=arm, GOARM=5, 6, and 7 correspond to the arm.5, arm.6, and arm.7 feature build tags. ...

Slide 15

Slide 15 text

Go command go generate への -skip の追加 にマッチする //go:generate ディレクティブをスキップ する go test への -skip の追加 にマッチするテスト、サブテスト、サンプルをスキップ する

Slide 16

Slide 16 text

Go command go build 、go install 等のビルド関連コマンドに -pgo flag が追加 フラグを付与すると、profile-guided optimization が有効化される アプリケーションの振る舞いに対してプロファイリングを行い、 その情報をコンパイラ最適化に使用する 詳細はこの後のCIARANA さんの発表をご覧ください https://go.dev/blog/pgo-preview

Slide 17

Slide 17 text

Go command (Cover) go build 、go install 等のビルド関連コマンドに -cover flag が追加 プログラムのコードカバレッジプロファイルを取得し、ファイルと して出力する 統合テストで使われることを意図している カバレッジ情報の収集は、ビルドされたバイナリの実行時に行わ れ、 GOCOVERDIR 環境変数で指定されたディレクトリに出力される 詳細はこの後のhiro さんの発表をご覧ください https://go.dev/testing/coverage/

Slide 18

Slide 18 text

Cgo C ツールチェーンのないシステム上で、デフォルトでcgo が無効になっ た CGO_ENABLED と CC 環境変数が設定されておらず、デフォルト のC コンパイラ (clang / gcc) がpath に見つからなければ CGO_ENABLED=0 となる 明示的な上書きは可能 cgo の使えない環境で、自動的にcgo の利用が選択されてしまい、 ビルドに失敗するようなケースを防ぐのが目的

Slide 19

Slide 19 text

Vet

Slide 20

Slide 20 text

ネストされた関数でのループ変数キャプチャの検知改良 サブテスト関数内の T.Parallel() 呼び出しに続くループ変数への参 照を検知するようになった

Slide 21

Slide 21 text

ネストされた関数でのループ変数キャプチャの検知改良 func TestToLower(t *testing.T) { tests := []struct { input string want string }{ {input: "A", want: "a"}, {input: "B", want: "b"}, } for _, tc := range tests { // tc := tc が抜けている t.Run(tc.input, func(t *testing.T) { t.Parallel() got := strings.ToLower(tc.input) if tc.want != got { t.Errorf("want: %s, got: %s", tc.want, got) } }) } }

Slide 22

Slide 22 text

ネストされた関数でのループ変数キャプチャの検知改良 vet の出力結果 $ go vet ./... ./func_test.go:27:27: loop variable tc captured by func literal ./func_test.go:28:7: loop variable tc captured by func literal ./func_test.go:29:35: loop variable tc captured by func literal

Slide 23

Slide 23 text

誤った時間形式の検知 Time.Format とtime.Parse での 2006-02-01 の使用を検知 2006-02-01 は yyyy-dd-mm に対応する、一般的でない形式 yyyy-mm-dd の誤りの可能性が高いので検知するようになった

Slide 24

Slide 24 text

Runtime GC の内部データ構造を再構成し、CPU 性能が最大2% 向上した

Slide 25

Slide 25 text

Compiler 匿名インタフェースの循環がデフォルトでコンパイルエラーとなるよ うになった インタフェースの埋め込みのトリッキーな使い方 Go 1.22 で言語仕様としてこれを許可しないようにする見込み type I interface { m() interface { I } }

Slide 26

Slide 26 text

Compiler Go 1.18 と1.19 でジェネリクス関連の対応がありビルド速度が低下し たが、Go 1.20 ではビルド速度が最大10% 向上し、Go 1.17 と同じレ ベルに戻った Go 1.19 と比較すると、生成されるコードのパフォーマンスも少し向 上している

Slide 27

Slide 27 text

Linker Linux リンク時に動的インタプリタとしてglibc またはmusl を選択するように なった Windows Go linker がLLVM ベースの現代的なC ツールチェーンをサポートした その他 コンパイラが生成するシンボルの接頭辞が go: と type: となる

Slide 28

Slide 28 text

Bootstrap Go 1.20 は、ブートストラップにGo 1.17.13 を必要とするようになっ た 1.18 / 1.19 は、まずGo 1.17 を探し、見付からなければ1.4 にフォー ルバックしていた 1.20 は、まずGo 1.17.13 を探し、その後1.4 にフォールバックする

Slide 29

Slide 29 text

Core library

Slide 30

Slide 30 text

crypto/ecdh package の追加 楕円曲線ディフィー・ヘルマン鍵共有 (ECDH) をサポートするための package が追加 ECDH は、ディフィー・ヘルマン鍵共有を、楕円曲線を使うように 変更したもの crypto/elliptic package をECDH の実装に使っているプログラムは、今 後は代わりにcrypto/ecdh を使うべき

Slide 31

Slide 31 text

複数エラーのラップ fmt.Errorf が、複数の %w を受け付けるように errors.Join 関数が追加 errors.Is / As は、ラップされた複数のエラーに対して検査を行うよう 変更された 詳しくは、この後のtenntenn さんの発表をご覧ください

Slide 32

Slide 32 text

HTTP ResponseController の追加 http.ResponseWriter をより簡単に操作出来るようにするために、 http.ResponseController が追加された これまでResponseWriter に対して(Flusher などに) 型アサーションし つつ呼んでいた機能や設定を普通のメソッド呼び出しで行える ResponseController 経由で行える操作は、Flush 、Hijack 、 SetReadDeadline 、SetWriteDeadline の4 つ // SetWriteDeadline の例 (https://go.dev/doc/go1.20 より引用) func RequestHandler(w ResponseWriter, r *Request) { rc := http.NewResponseController(w) rc.SetWriteDeadline(time.Time{}) // disable Server.WriteTimeout when sending a large response io.Copy(w, bigData) }

Slide 33

Slide 33 text

httputil.ReverseProxy へのRewrite hook の追 加 httputil.ReverseProxy に、Rewrite hook が追加された もともと存在していたDirector hook には、hook 内で追加したHTTP Header が意図せず削除される(追加出来ない)場合があると言う 問題があった Rewrite hook によって、Director hook を置き換える フューチャー技術ブログの棚井さんの記事に詳細な解説があります https://future-architect.github.io/articles/20230131a/

Slide 34

Slide 34 text

strings / bytes package CutPrefix / CutSuffix 関数の追加 TrimPrefix / TrimSuffix と同様の機能に加え、トリムが発生したかど うかを報告する Clone 関数の追加 (bytes のみ) byte slice のコピーを作成する package strings func CutPrefix(s, prefix string) (after string, found bool) func CutSuffix(s, suffix string) (before string, found bool) package bytes func CutPrefix(s, prefix []byte) (after []byte, found bool) func CutSuffix(s, suffix []byte) (before []byte, found bool) func Clone(b []byte) []byte

Slide 35

Slide 35 text

context package WithCancelCause 関数、Cause 関数の追加 WithCancelCause は、WithCancel と異なり、エラーを引数に受け 取るキャンセル関数を返す context をキャンセルした理由を、このキャンセル関数に渡すこ とが出来る Cause 関数を使うことで、キャンセルされた理由のerror を取り出す ことが出来る context 自身のErr() メソッドは、引き続きcontext.Canceled エラー を返す

Slide 36

Slide 36 text

context package // ドキュメントの例: https://pkg.go.dev/context#WithCancelCause より引用 ctx, cancel := context.WithCancelCause(parent) cancel(myError) ctx.Err() // returns context.Canceled context.Cause(ctx) // returns myError

Slide 37

Slide 37 text

time package DateTime, DateOnly, TimeOnly の3 つの最もよく使われる時間のフォ ーマット定数が追加された 時間同士を比較するTime.Compare メソッドが追加された const ( DateTime = "2006-01-02 15:04:05" DateOnly = "2006-01-02" TimeOnly = "15:04:05" ) // t がu より前なら-1 、t がu より後なら+1 、同じなら0 が返る func (t Time) Compare(u Time) int

Slide 38

Slide 38 text

sync package sync.Map に Swap, CompareAndSwap, CompareAndDelete が追加 された

Slide 39

Slide 39 text

reflect package Value.Comparable メソッドの追加 v.Interface() == x がどんなx に対してもpanic しないかを返す Value.Equal メソッドの追加 値が等しいかどうかを返す。比較される型がcomparable でない場 合はpanic する Value.Grow() slice のcapacity を増加させる Value.SetZero() Value の保持する型のゼロ値を設定する

Slide 40

Slide 40 text

arena package メモリをマニュアルで確保したり、解放するのに使える機能 Go 1.20 で試験的に導入。正式リリース前のリリースノートには載って いましたが、試験的な機能をリリースノートに載せると意図しない反 響を招く可能性が高いと判断され、最終的には掲載されていません 詳細については、この後のsivchari さんの発表をご覧ください

Slide 41

Slide 41 text

おすすめ記事 CIARANA さんの "Go 1.20 New Features" この発表で紹介しきれていない内容についても詳細に説明されてい ます https://zenn.dev/koya_iwamura/articles/bb9b590b57d825 フューチャーさんのGo 1.20 リリース連載 https://future-architect.github.io/articles/20230123a/