Open1
Goの標準ライブラリにmapsというものを今更ながら知った

マップのコピー、キーの削除、比較などの操作が簡単に行えそう
主な機能としては:
-
maps.Clone
- マップのコピーを作成 -
maps.Equal
- 2つのマップが等しいかどうか比較 -
maps.EqualFunc
- カスタム比較関数を使用してマップを比較 -
maps.DeleteFunc
- 条件に合うキーと値のペアを削除 -
maps.Copy
- ソースマップのすべてのキー/値ペアのコピーを作成
Equal
func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool
- 目的: 2つのマップが同じキー/値ペアを持つかどうかを確認します
-
ジェネリクス:
M1
とM2
はmap[K]V
型、K
とV
は比較可能な型 -
動作:
- まずマップのサイズが異なる場合は即座に
false
を返します -
m1
の各キーと値に対して、同じキーがm2
に存在し、かつ値が等しいか(==
演算子で比較)を確認します - すべてのキー/値ペアが一致すれば
true
を返します
- まずマップのサイズが異なる場合は即座に
- 使用例: 2つの設定マップが同じかどうかの確認など
EqualFunc
func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool
- 目的: カスタム比較関数を使用して2つのマップを比較します
-
ジェネリクス:
-
M1
はmap[K]V1
型、M2
はmap[K]V2
型 -
K
は比較可能な型、V1
とV2
は任意の型
-
-
動作:
-
Equal
と同様にマップサイズを比較 - 値の比較に
==
の代わりに、渡されたeq
関数を使用
-
- 使用ケース: 値が複雑な構造体の場合や、特定のフィールドのみを比較したい場合に便利
Clone
func Clone[M ~map[K]V, K comparable, V any](m M) M
- 目的: マップのコピーを作成します(シャローコピー)
-
ジェネリクス:
M
はmap[K]V
型、K
は比較可能な型、V
は任意の型 -
動作:
- 元のマップが
nil
の場合はnil
を返します - それ以外の場合、内部の
clone
関数を使用して新しいマップを作成
- 元のマップが
- シャローコピー: ネストされたマップや構造体はコピーされません(参照のみコピー)
Copy
func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2)
-
目的: ソースマップ(
src
)のすべてのキー/値ペアを宛先マップ(dst
)にコピーします -
ジェネリクス:
M1
とM2
はmap[K]V
型、K
は比較可能な型、V
は任意の型 -
動作:
-
src
の各キー/値ペアをdst
に追加します - キーが既に存在する場合は、値が上書きされます
-
-
違い:
Clone
が新しいマップを作成するのに対し、Copy
は既存のマップに追加します
DeleteFunc
func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool)
- 目的: 指定された条件を満たすキー/値ペアをマップから削除します
-
ジェネリクス:
M
はmap[K]V
型、K
は比較可能な型、V
は任意の型 -
動作:
- マップの各キー/値ペアに対して、渡された
del
関数を呼び出します -
del
関数がtrue
を返す場合、そのキー/値ペアを削除します
- マップの各キー/値ペアに対して、渡された
- 使用例: 特定の条件(古すぎる値、無効な値など)に基づいてマップをフィルタリングする場合
これらの関数は、マップ操作を簡素化し、コード量を減らすことができるため、Go 1.21以降のプロジェクトでは積極的に活用することをお勧めします。
実コード
package maps
import (
_ "unsafe"
)
// Equal reports whether two maps contain the same key/value pairs.
// Values are compared using ==.
func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool {
if len(m1) != len(m2) {
return false
}
for k, v1 := range m1 {
if v2, ok := m2[k]; !ok || v1 != v2 {
return false
}
}
return true
}
// EqualFunc is like Equal, but compares values using eq.
// Keys are still compared with ==.
func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool {
if len(m1) != len(m2) {
return false
}
for k, v1 := range m1 {
if v2, ok := m2[k]; !ok || !eq(v1, v2) {
return false
}
}
return true
}
// clone is implemented in the runtime package.
//
//go:linkname clone maps.clone
func clone(m any) any
// Clone returns a copy of m. This is a shallow clone:
// the new keys and values are set using ordinary assignment.
func Clone[M ~map[K]V, K comparable, V any](m M) M {
// Preserve nil in case it matters.
if m == nil {
return nil
}
return clone(m).(M)
}
// Copy copies all key/value pairs in src adding them to dst.
// When a key in src is already present in dst,
// the value in dst will be overwritten by the value associated
// with the key in src.
func Copy[M1 ~map[K]V, M2 ~map[K]V, K comparable, V any](dst M1, src M2) {
for k, v := range src {
dst[k] = v
}
}
// DeleteFunc deletes any key/value pairs from m for which del returns true.
func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) {
for k, v := range m {
if del(k, v) {
delete(m, k)
}
}
}