概要
小ネタ。せっかくサンプル作ったので、ここにメモメモ。
チャネルを使って処理することはよくありますが、チャネルのデータをスライスにしてしまいたいときも結構あります。
Go 1.18 までは、それぞれの型ごとに処理を書く必要がありましたが、1.18 でジェネリックが導入されたので、それも楽に出来るようになりました。
サンプル
package chans import "context" // SliceContext は、Slice の context.Context 版です. func SliceContext[T any](ctx context.Context, in <-chan T) []T { return Slice(ctx.Done(), in) } // Slice は、指定されたチャネルから情報を読み取りスライスにして返します. // // 本処理は、done もしくは in のどちらかがクローズされるまで結果を返しません。 func Slice[T any](done <-chan struct{}, in <-chan T) []T { var ( ret = make([]T, 0) ) LOOP: for { select { case <-done: break LOOP case v, ok := <-in: if !ok { break LOOP } ret = append(ret, v) } } return ret }
func ExampleSliceContext() { var ( rootCtx = context.Background() ctx, cxl = context.WithCancel(rootCtx) ) defer cxl() var ( values = []int{1, 2, 3, 4, 5} in = chans.GeneratorContext(ctx, values...) out = chans.SliceContext(ctx, in) ) fmt.Printf("%[1]v (%[1]T)", out) // Output: // [1 2 3 4 5] ([]int) }
チャネル関連の記事
Goのチャネル関連の記事は前に結構書いたので、よろしければご参考まで。
上の記事のソースは以下にあります。
参考情報
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。