Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What's new in Go 1.20?

syumai
February 21, 2023

What's new in Go 1.20?

Go 1.20 リリースパーティーの発表資料です
* https://gocon.connpass.com/event/273096/

関連するおすすめ記事
* https://zenn.dev/koya_iwamura/articles/bb9b590b57d825
* https://future-architect.github.io/articles/20230123a/

syumai

February 21, 2023
Tweet

More Decks by syumai

Other Decks in Programming

Transcript

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

    View full-size slide

  2. 自己紹介
    syumai
    Go Documentation
    輪読会 / ECMAScript
    仕様輪
    読会 主催
    株式会社ベースマキナで管理画面のSaaS
    を開発中
    Go
    でGraphQL
    サーバー (gqlgen)
    や TypeScript

    フロントエンドを書いています
    Twitter: @__syumai
    Website: https://syum.ai

    View full-size slide

  3. 言語仕様の変更

    View full-size slide

  4. スライスから配列への変換
    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

    View full-size slide

  5. 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

    View full-size slide

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

    View full-size slide

  7. 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

    View full-size slide

  8. 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
    以上が必要

    View full-size slide

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

    View full-size slide

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

    に変更される

    View full-size slide

  11. 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.
    ...

    View full-size slide

  12. Go command
    go generate
    への
    -skip
    の追加

    にマッチする
    //go:generate
    ディレクティブをスキップ
    する
    go test
    への
    -skip
    の追加

    にマッチするテスト、サブテスト、サンプルをスキップ
    する

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. Cgo
    C
    ツールチェーンのないシステム上で、デフォルトでcgo
    が無効になっ

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

    View full-size slide

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

    View full-size slide

  17. ネストされた関数でのループ変数キャプチャの検知改良
    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)
    }
    })
    }
    }

    View full-size slide

  18. ネストされた関数でのループ変数キャプチャの検知改良
    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

    View full-size slide

  19. 誤った時間形式の検知
    Time.Format
    とtime.Parse
    での
    2006-02-01
    の使用を検知
    2006-02-01

    yyyy-dd-mm
    に対応する、一般的でない形式
    yyyy-mm-dd
    の誤りの可能性が高いので検知するようになった

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  24. 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
    にフォールバックする

    View full-size slide

  25. Core library

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  28. 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)
    }

    View full-size slide

  29. httputil.ReverseProxy
    へのRewrite hook
    の追

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

    View full-size slide

  30. 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

    View full-size slide

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

    View full-size slide

  32. 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

    View full-size slide

  33. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide