HN 日本語サマリー

← 一覧へ戻る
プログラミング

Golang提案: container/: ジェネリックコレクション型

Golang proposal: container/: generic collection types (github.com)

167 pointsby jabits144 コメント

要約

Go言語のコレクションワーキンググループは、Go 1.28に向けて標準ライブラリに一般的なコレクションデータ構造(ハッシュマップ、セット、順序付きマップ、バイナリヒープなど)を導入する提案を発表しました。ジェネリクスとイテレータの追加により、より人間工学的なAPIと効率的な実装が可能になり、既存のコードとの互換性も考慮されています。

全文翻訳

おっと!読み込み中にエラーが発生しました。ページを再読み込みしてください。golang / go 公開通知通知設定を変更するにはサインインが必要です フォーク 19.2k スター 135k提案:container/...:ジェネリックコレクション型 #80590新規イシューコピーリンク新規イシューコピーリンクオープンオープン提案:container/...:ジェネリックコレクション型#80590コピーリンクラベル提案マイルストーンGo1.28説明adonovan2026年7月28日にオープンイシュー本文アクション背景:Goコレクションワーキンググループは、2025年後半に、実用性とシンプルさというGoの馴染み深い原則に導かれ、標準ライブラリに一般的なコレクションデータ構造をもたらす目的で設立されました。姓のアルファベット順に、グループはJonathan Amsterdam(@jba)、Alan Donovan(@adonovan)、Robert Griesemer(@griesemer)、Daniel Martí(@mvdan)、Roger Peppe(@rogpeppe)、Keith Randall(@khr)、Ian Lance Taylor(@ianlancetaylor)で構成されています。私たちは今、コミュニティと結果を共有する準備ができた段階に達しました。このイシューは、Go 1.28向けの新しいコレクションAPIに関するいくつかの関連提案を議論するためのアンブレラです。テーマの概要と、さまざまな具体的な提案および関連する実装CLへのリンクを示します。Goは現在、ライブラリにほとんどコレクションタイプを提供しておらず、当初から組み込みのスライスとマップ型の柔軟性を強調してきました。提供されている中で最も重要なのは、優先度キューに使用されるヒープです。セットさえも欠けています。それらは慣習的にmap[T]boolまたはmap[T]struct{}の用語で表現されます。バイナリツリーに基づく順序付きマップとセットは完全に欠けています。Go 1.18でのジェネリクスの追加とGo 1.23でのイテレータの追加により、ライブラリ定義型が組み込み型と同等の人間工学を達成できるようになり、スライスとマップに対する多くの一般的な操作がライブラリ関数への呼び出しとして表現できるようになりました。この作業は、より重要なデータ型のいくつかを標準ライブラリに追加し、それらのAPIおよび将来の追加のAPIの慣例を確立することを目的としています。提案:提案されている追加には以下が含まれます:#70471、CL 657296(go1.27でリリース):hash/maphash.Hasher:カスタムハッシュ関数と任意のデータ型の同値関係を表現するための標準インターフェース。これらは、map[K]Vで使用されるコンパイラ定義のものとは異なり、キー型が比較不可能(スライスやマップなど)である場合、またはデフォルトの比較が間違った結果を生成する場合(例えば、deep comparison operation types.Identical を必要とする types.Type 値の場合)に役立ちます。そのパッケージドキュメントには、ブルームフィルターでの使用例が含まれています。#69559、CL 612217:container/hash.Map[K,V]:上記のカスタムハッシュ関数を使用するハッシュベースのMap。#80584、CL 741160:container/hash.Set[T]:同様のライン上のハッシュベースのSet。#69230、CL 745441:container/set.Set[T]:比較可能な要素を持つセットの標準データ型。これはmap[T]struct{}として透過的に表現され、UnionやIntersectionなどのすべての通常のセット操作をサポートします。これは「レガシー」セット(map[T]boolおよびmap[T]struct{}に基づく)よりも便利であり、map[T]boolの潜在的な偽値に関する曖昧さを回避します。ほとんどの新しいGo APIで標準セットになると予想されます。#77052、CL 724420:container/mapset:APIを変更できない既存のコードで、レガシーセットをセットとして便利に操作するためのヘルパー関数(Union、Intersectionなど)のパッケージ。これらの関数はset.Setのメソッドと完全に並列です。#60630:container/ordered.Map[K,V]:順序付きマッピング。現在の実装は平衡二分木を使用していますが、設計上それに依存しているわけではありません。map[K]Vを作成してからキーをソートするという一般的なGoパターンは、ほとんどの場合うまく機能しますが、範囲クエリが必要な場合など、他のデータ構造がはるかに優れたパフォーマンスを発揮することがあります。#77397:container/heap/v2.Heap:標準ライブラリの既存のヒープを置き換えるジェネリックバイナリヒープAPI。既存のヒープは使用が難しい場合があります。将来的には、挿入順序付きハッシュマップ(#80194)やスタックなどの追加の提案を検討する予定です。提案されているすべてのデータ構造の初期実装は、APIおよび漸近的パフォーマンスの期待を可能な限りシンプルに満たすことを目指しています。定数係数を削減するための最適化の機会は間違いなくたくさんありますが、それらは提案プロセスの範囲外です。新しいパッケージは既存のcontainerツリーに配置されますが、Linuxのコンテナ仮想化の概念との混同を避けるために「コレクション」という用語を好みます。抽象コレクション制約インターフェース新しいMapおよびSet型のほとんどのメソッドは、特定の具体的な表現型に固有のものではなく、すべてのMapおよびSetに共通しています。「バイナリメソッド問題」のため、それらは実際には共通インターフェース型の実装ではありません。各セットデータ型Sがfunc (S) Union(S) Sの形式のUnionメソッドを持つ場合、異なるセット型のUnionメソッドは互換性がないため、共通の通常のインターフェースを持ちません。この抽象Set型を表現するには、Fバウンド多相または再帰制約インターフェースを使用する必要があります。CL 761460は、パッケージ実装者が具体的なコレクション、セット、またはマップ型の範囲で機能する抽象ヘルパー関数(ContainsAny、Subset、Arbitraryなど)を記述できるようにする、非エクスポートされた抽象Collection、Set、およびMap制約インターフェース型をcontainerパッケージに追加します。これらは、高レベルの全体像を把握するのに役立つように、簡単なコメントとともに以下に再現しますが、提案の一部ではありません。それらはテストでの適合性を保証するだけです。詳細については、個々の提案を参照してください。// _AbstractCollectionは、*hash.Map、*hash.Set、*ordered.Map、またはset.Setなどの要素EのコレクションCをモデル化します。type _AbstractCollection[E any, C _AbstractCollection[E, C]] interface { Clear() Clone() C Contains(E) bool ContainsAll(iter.Seq[E]) bool Len() int String() string } // _AbstractMapは、*hash.Mapまたは*ordered.MapなどのキーKから値VへのマッピングMをモデル化します。type _AbstractMap[K, V any, M _AbstractMap[K, V, M]] interface { _AbstractCollection[K, M] All() iter.Seq2[K, V] At(K) V Delete(K) (V, bool) DeleteAll(iter.Seq[K]) bool DeleteFunc(func(K, V) bool) bool Get(K) (V, bool) Keys() iter.Seq[K] Set(K, V) (V, bool) SetAll(iter.Seq2[K, V]) bool Values() iter.Seq[V] } // _AbstractSetは、*hash.Setまたはset.Setなどの要素EのセットSをモデル化します。type _AbstractSet[E any, S _AbstractSet[E, S]] interface { _AbstractCollection[E, S] All() iter.Seq[E] Delete(E) bool DeleteAll(iter.Seq[E]) bool DeleteFunc(func(E) bool) bool Difference(S) S DifferenceWith(S) Equal(S) bool Insert(E) bool InsertAll(iter.Seq[E]) bool Intersection(S) S IntersectionWith(S) Intersects(S) bool SymmetricDifference(S) S SymmetricDifferenceWith(S) Union(S) S UnionWith(S) } 現時点では、これらの抽象型は非エクスポートであり、Goの慣例のドキュメントとして機能し、一貫性を確保するのに役立ちます。これらを公開する予定はありませんが、具体的なコレクション型での経験を積んだ後に、将来のリリースで公開する可能性があります。それまでの間、ユーザーは必要に応じて最小限の制約型を定義できます。たとえば、抽象セットに対するジェネリックTake関数(CL 761460から)の例のように:// _TakeSetは、[Take]関数に十分なセットの抽象化を定義します。type _TakeSet[E any, S _TakeSet[E, S]] interface { All() iter.Seq[E] Delete(E) bool } // Takeはセットから任意の要素を削除して返します。// セットが空だった場合はゼロを返します。func Take[S _TakeSet[E, S], E any](set S) (e E, found bool) { for e = range set.All() { found = true set.Delete(e) break } return } 各インターフェースに含まれるメソッドのセットには、ある程度の任意性があります。一部のデータ構造では、メソッドがより効率的な特殊化された実装を許可します。しかし、すべての可能な操作がインターフェースに追加された場合、実装者の負担は不当になります。例えば、Setインターフェースには