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

go-generic-libraries

 go-generic-libraries

Masafumi Yamamoto

August 03, 2022
Tweet

Other Decks in Programming

Transcript

  1. go1.18 型パラメータを用いたGenerics導入👏 Go @golang·Follow Go go1.18 is released! Release notes:

    go.dev/doc/go1.18 Download: go.dev/dl/#go1.18 #golang 2:36 AM · Mar 16, 2022 3.5K Reply Copy link Read 63 replies
  2. Without Generics 具体的なデータ型 抽象的に func main() { SplitInt([]int{1, 2, 3,

    4}) // [1 2] [3 4] SplitStr([]string{"foo", "bar"}) // [foo] [bar] } func SplitInt(v []int) ([]int, []int) { mid := len(v) / 2 return v[:mid], v[mid:] } func SplitStr(v []string) ([]string, []string) { mid := len(v) / 2 return v[:mid], v[mid:] } func Split(v []interface{}) ([]interface{}, []interface{}) mid := len(v) / 2 return v[:mid], v[mid:] }
  3. 都度 型アサーション v1, _ := Split([]interface{}{1, "hoge", 3, 4}) vint,

    ok := v.(int) if ok { func main() { sum := 0 for _, v := range v1 { sum += vint } } fmt.Println(sum) }
  4. With Generics 具体的なデータ型 抽象的に func main() { SplitInt([]int{1, 2, 3,

    4}) // [1 2] [3 4] SplitStr([]string{"foo", "bar"}) // [foo] [bar] } func SplitInt(v []int) ([]int, []int) { mid := len(v) / 2 return v[:mid], v[mid:] } func SplitStr(v []string) ([]string, []string) { mid := len(v) / 2 return v[:mid], v[mid:] } func Split[T any](v []T) ([]T, []T) { mid := len(v) / 2 return v[:mid], v[mid:] }
  5. 型安全に、抽象化! func main() { // v1, _ := Split([]int{1, "hoge",

    3, 4}) (untyped string constant) as int value in array or slice literal v1, _ := Split([]int{1, 2, 3, 4}) sum := 0 for _, v := range v1 { sum += v } fmt.Println(sum) }
  6. lo lodashスタイルのライブラリ。たくさん機能がある Slice操作関数。Filter,Map,Reduce,Uniq... map操作関数。FindKey,Keys,Values,Assign... github.com/samber/lo numbers := []int{1, 2, 3,

    4} lo.Filter(numbers, func(x int, _ int) bool { return x%2 == 0 }) // []int{2, 4} lo.Map(numbers, func(x int, _ int) int { return x * 2 }) // []int{2, 4, 6, 8} mapA := map[string]int{"foo": 10} mapB := map[string]int{"bar": 20} lo.FindKey(mapA, 10) // foo, true lo.Assign(mapA, mapB) // map[string]int{"foo": 10, "bar": 20}
  7. loのMap関数実装 T型スライスと、T=>Rにする関数を引数にとって、R型スライスを返す func Map[T any, R any](collection []T, iteratee func(T,

    int) R) []R { result := make([]R, len(collection)) for i, item := range collection { result[i] = iteratee(item, i) } return result }
  8. pie Slice, Map操作のためのユーティリティ関数ライブラリ。メソッドチェインで操作できる github.com/elliotchance/pie/v2 numbers := []int{1, 2, 3, 4}

    pie.Of(numbers). Filter(func(x int) bool { return x%2 == 0 }). // {[2, 4]} Map(func(x int) int { return x * 2 }). // {[4, 8]} Reverse(). // {[8, 4]} Result // [8, 4]
  9. 便利!👏でも、型変換しようとするとエラーになる numbers := []int{1, 2, 3, 4} pie.Of(numbers). Map(func(x int)

    string { return strconv.Itoa(x) + "x" }) // 期待 []string{1x, 2x, 3x, 4x} // cannot use func(x int) string {…} (value of type func(x int) string) // as type func(int) int in argument to pie.Of(numbers).Map
  10. pieのMapメソッド実装 T型スライスと、T=>Tにする関数を引数にとって、T型スライスを返す…? オモッテタントチガウ…🤔 func (o OfSlice[T]) Map(fn func(T) T) OfSlice[T]

    { return OfSlice[T]{Map(o.Result, fn)} } func (o OfSlice[T]) Map[E any](fn func(T) E) OfSlice[E] { return OfSlice[E]{Map(o.Result, fn)} }
  11. 参考 Type Parameters Proposal https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md When To Use Generics https://go.dev/blog/when-generics

    An Introduction To Generics https://go.dev/blog/intro-generics github.com/samber/lo github.com/elliotchance/pie/v2