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

What's new in Go 1.18?

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for syumai syumai
February 18, 2022

What's new in Go 1.18?

Go 1.18 リリースパーティーにて発表の資料です。
https://gocon.connpass.com/event/234198/

Avatar for syumai

syumai

February 18, 2022
Tweet

More Decks by syumai

Other Decks in Programming

Transcript

  1. Go 1.18 の目玉機能 Generics Fuzzing Workspace mode net/netip package Generics

    以外の 3 つについては、別途発表がありますのでそちらにお 任せします!
  2. 型パラメータ 型定義 (type definition) と 関数宣言 (function declaration) に、型パ ラメータを追加することが出来るようになる。

    // 型定義の例 type Vector[T any] []T type Map[K comparable, V any] map[K]V // 型パラメータは複数持てる type Pair[A, B any] struct { a A; b B } // 連続する型パラメータの制約が共通な時は省略も可能 // 関数宣言の例 func Min[T constraints.Ordered](a, b T) T { if a < b { return a } return b }
  3. 型引数、 インスタンス化 パラメータ化された型、関数の型パラメータは 型引数 (type arguments) によって置き換えられ、インスタンス化 (instantiation) さ れる。

    インスタンス化の結果、新たな型、関数が生成され、それを使うこ とが出来ると言うイメージ。 func Min[T constraints.Ordered](a, b T) T { ... } // func Min[int](a, b int) int { ... } // `int` への置き換えイメージ // func Min[float64](a, b float64) float64 { ... } // `float64` への置き換えイメージ func main() { fmt.Println(Min[int](1, 2)) // `T` が 型引数 `int` に置き換わる => 1 fmt.Println(Min[float64](1.5, 0.5)) // `T` が 型引数 `float64` に置き換わる => 0.5 }
  4. 型推論 型引数は、型推論 (type inference) のアルゴリズムによって推論可能 な場合は省略することが出来る。 型推論には 関数引数型推論 (function argument

    type inference) 、 制約型推論 (constraint type inference) の 2 種類が存在し、これら を組み合わせたアルゴリズムで動作する ( ここでは踏み込んだ解説 を行わない) // 関数の引数から型引数を推論する例 func main() { fmt.Println(Min(1, 2)) // `int` が推論される // fmt.Println(Min[int](1, 2)) // 上の行と同等 fmt.Println(Min(1.5, 0.5)) // `float64` が推論される // fmt.Println(Min[float64](1.5, 0.5)) // 上の行と同等 }
  5. 型制約 型パラメータは、型制約 (type constraints) によって受け付ける型引 数を制限することができ、型制約によって行える操作も変わる。 型制約は、インタフェース (interfaces) によって表現される。 //

    fmt.Stringer インタフェースを型制約とする func PrintStringer[T fmt.Stringer](v T) { fmt.Println(v.String()) // ここで String() メソッドを呼べる } type StringableInt int func (i StringableInt) String() string { ... } func main() { PrintStringer(StringableInt(1)) // OK PrintStringer(1) // NG: int does not implement fmt.Stringer }
  6. インタフェースの記法の拡張 インタフェース要素 (interface elements) として、型要素 (type elements) を持つことが出来るようになる。 型要素は、 |

    で連結された型で表され、例えば、下記のような int 型または string 型のみを受け付ける型を書くことが出来る。 type IntOrString1 interface { int | string } type IntOrStrings1[T IntOrString1] []T func main() { _ = IntOrStrings1[int]{1, 2, 3} // OK _ = IntOrStrings1[string]{"a", "b", "c"} // OK _ = IntOrStrings1[float64]{1.0, 2.0, 3.0} // NG }
  7. インタフェースの記法の拡張 加えて、 type MyInt int といった、型定義によって導入された型を 受け付けられるようにするため、 ~ 記号を型要素内の型名に付与す る記法が追加された。

    ~T は、T 型を基底型 (underlying type) に持つ型の集合を表す。 type IntOrString1 interface { int | string } // `~` なし type IntOrStrings1[T IntOrString1] []T type IntOrString2 interface { ~int | ~string } // `~` あり type IntOrStrings2[T IntOrString2] []T type MyInt int func main() { _ = IntOrStrings1[MyInt]{1, 2, 3} // NG _ = IntOrStrings2[MyInt]{1, 2, 3} // OK }
  8. インタフェースの記法の拡張 型要素は、旧来のメソッド宣言である メソッド要素 (method elements) と合わせて使うことが出来る。 例えば、int 型に対して定義された、 String() string

    メソッドを持つ 型への制約は次のように書ける。 type IntStringer interface { ~int // 型要素 String() string // メソッド要素 } func PrintIntStringer[T IntStringer](v T) { fmt.Println(v.String()) } type MyStringableInt int func (i MyStringableInt) String() string { ... } func main() { PrintIntStringer(MyStringableInt(100)) // OK }
  9. 応用編 ( さわりだけ話します) インタフェースは、型集合 (type sets) を表す概念となる。 interface { int

    | string } は、int 型とstring 型のみからなる有限 個の型の集合。 interface { ~int } は、int 型に対して定義された型からなる無限個 の型の集合。 interface { String() string } は、 String() string メソッドを実 装する無限個の型からなる集合。
  10. 応用編 ( さわりだけ話します) インタフェースの実装 (implements interface) の概念も変わる。 これまでは、ある型T がインタフェースの持つメソッドを全て実装 していることを指していた。

    新しい仕様では、ある型T がインタフェースの型集合に含まれてい ることを 実装している と言う。 type IntOrString interface { int | string } // int 型 => 実装している // float64 型 => 実装していない type Stringer interface { String() string } type MyInt int func (i MyInt) String() string { ... } // int 型 => 実装していない // MyInt 型 => 実装している
  11. 応用編 ( 今回はskip) インタフェース要素も、それぞれが型集合を表す。 型要素 int は、int 型のみからなる集合 型要素 ~int

    は、int 型を基底型に持つ型からなる集合 メソッド要素 String() string は、このメソッドを実装している型 からなる集合
  12. 応用編 ( 今回はskip) | の両側の要素、 type term もそれぞれが型集合を表し、全体が各要 素の型集合の 和集合

    (union) を表す。 ~int | ~string は、int 型を基底型に持つ型からなる集合と、string 型を基底型に持つ型からなる集合の和集合 インタフェース全体の型集合は、そのインタフェースが持つインタフ ェース要素それぞれの型集合の積集合。 interface { ~int; String() string } の型集合は、int 型を基底型に 持つ型の集合と、String メソッドを実装している型の集合の積集 合。
  13. 応用編 ( 今回はskip) 他のインタフェースをインタフェースの型要素に含むこともでき、こ れをインタフェースの埋め込み (embedded interface) と言う。 | による和集合、複数のインタフェース要素からなる積集合につい

    てのルールが、インタフェースの埋め込みに対しても適用される。 これによって、旧来のインタフェースの埋め込みと互換性を保つ ことが出来ている。
  14. 型制約の省略記法 利便性のため、型制約内の interface { } は省略することが出来る。 func PrintInt[T interface {

    ~int }](v T) { ... } func PrintInt[T ~int](v T) { ... } // 上の行と同等 map, slice, channel などの要素型を持つ型を受け取るジェネリックな 関数を書くのに便利。 下記は、maps (https://pkg.go.dev/golang.org/x/exp/maps) の例 // Clone returns a copy of m. func Clone[M ~map[K]V, K comparable, V any](m M) M // `map[K]V` 型ではなく、 `M` 型 (map[K]V 型を基底型に持つ型) の値を返せるのがポイント。
  15. comparable !=, == によって比較可能なインタフェース以外の型を表す制約。 インタフェース型の場合は、そのインタフェースの含む型が全て比 較可能でないといけない。 comparable は型制約でしか使うことが出来ない。 func Equal[T

    comparable](a, b T) bool { return a == b } func main() { fmt.Println(Equal(1, 2)) // OK: => false var a, b interface{} a = 1 b = 2 fmt.Println(Equal(a, b)) // NG: interface{} does not implement comparable }
  16. constraints, slices, maps ジェネリクスに関連した 3 つの package が golang.org/x/exp に追加

    される。 golang.org/x/exp/constraints golang.org/x/exp/slices golang.org/x/exp/maps Go 1.18 では、ジェネリクスに関連した標準ライブラリの変更は行わ れない。
  17. constraints package Float , Integer , Ordered といった、頻繁に使われる型制約の定義を まとめた package

    。 Ordered は、 < <= >= > 記号で順序付け可能な型に対する制約。 // スライド冒頭の Min 関数の例 import "golang.org/x/exp/constraints" func Min[T constraints.Ordered](a, b T) bool { if a < b { return a } return b }
  18. 型エイリアス 型エイリアスが型パラメータを持てるようにする Proposal は accept されている https://github.com/golang/go/issues/46477 リリースは Go 1.19

    以降に持ち越し type Vector[T any] []T type IntVector = Vector[int] // OK ( 型エイリアス宣言は型パラメータを持っていない) type Map[K comparable, V any] map[K]V type StringMap[V any] = Map[string]V // NG (Go 1.18 時点では書けないが、将来的には書けるようになる見込み)
  19. メソッド メソッド宣言への型パラメータの追加は、実装上の都合でリリースの 見込みが立っていない https://go.googlesource.com/proposal/+/refs/heads/master/desi gn/43651-type-parameters.md#No-parameterized-methods type Vector[A any] []A //

    このようなメソッド宣言は書けない func (v Vector[A]) Map[B any](f func(v A) B) Vector[B] { ... } func main() { v := Vector[int]{1, 2, 3} v.Map[string](func (v int) string { ... }).Map ... }
  20. 現時点のジェネリクスで出来ないこと 複合型の要素による型推論 type Ints[T constraints.Integer] []T と言う型があった時、 Ints{1, 2, 3}

    とは書けず、 Ints[int]{1, 2, 3} と型引数を明示す る必要がある 現時点で実装の見込みは立っていない。Type Parameters Proposal に言及あり
  21. 現時点のジェネリクスで出来ないこと ジェネリックな関数の中で型宣言が出来ない Go 1.19 で実装したいとのこと 事前宣言された real, imag, complex 関数を型パラメータ型で宣言さ

    れた関数の引数として渡すことが出来ない Go 1.19 で制限を外したいとのこと 構造体型に型パラメータ型を埋め込むことが出来ない | による型集合の和集合の要素として、メソッドを持つインタフェー スを含むことが出来ない これが許可されるようになるかは未定とのこと
  22. より詳しく知りたい方はこちら The Go Programming Language Specification - Go 1.18 Draft

    https://tip.golang.org/ref/spec Type parameters proposal https://go.googlesource.com/proposal/+/refs/heads/master/desi gn/43651-type-parameters.md 初めての型セット - @shino_nobishii https://speakerdeck.com/nobishino/introduction-to-type-sets
  23. TLS 1.0 and 1.1 disabled by default client- side Config.MinVersion

    が設定されていなければ、 クライアントサイドの コネクションのデフォルトとして TLS 1.2 をに使うようになった。 Config.MinVersion を指定すれば、 TLS 1.0 / 1.1 も使える。 サーバーサイドのデフォルトは TLS 1.0 のまま。