メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

新機能

hash/maphashに、comparable型向けのHasher実装を簡単に得られるComparableHasher型が追加された

hash/maphash

この項目の注釈は AI により生成されており、誤りを含む場合があります。
使用例のコンパイル検証: 検証済み

概要

hash/maphashパッケージにComparableHasher[T]型が追加された。これはHasher[T]インターフェースの実装であり、Equalメソッドが==と一致するように定義されている。comparable型をBloom filterなど独自のハッシュベースのデータ構造で扱いたい場合に、Hash/Equalメソッドを自前で書かずに済む。

使用例

Before

package main

import "hash/maphash"

// comparable型向けのHasherを使うには、Hash/Equalメソッドを
// 自前で実装する必要があった。
type stringHasher struct{}

func (stringHasher) Hash(h *maphash.Hash, s string) {
	maphash.WriteComparable(h, s)
}

func (stringHasher) Equal(x, y string) bool { return x == y }

func main() {
	var hasher maphash.Hasher[string] = stringHasher{}
	_ = hasher
}

After

package main

import "hash/maphash"

func main() {
	// comparable型であれば ComparableHasher をそのまま使える。
	var hasher maphash.Hasher[string] = maphash.ComparableHasher[string]{}
	_ = hasher
}

移行時の注意

追加のみの変更であり、既存コードへの影響はない。ただしComparableHasher[T]は型パラメータTcomparable制約を満たすことのみを要求しており、ComparableHasher[any]のような具体化自体はコンパイルが通ってしまう。この場合、Hash/Equalに非comparableな値を渡すと実行時パニックになるため、実際に渡す値がcomparableであることは呼び出し側の責任で保証する必要がある。

実装解説

ComparableHasher[T]は空のstructで、HashメソッドはWriteComparableを呼ぶだけ、Equalメソッドは単純にx == yを返すだけの実装になっている(hasher.go;l=138)。

構造体には_ [0]func(T)という長さ0のフィールドが定義されている(hasher.go;l=135)。関数型フィールドを持たせることでComparableHasher[T]自体を==で比較できないようにし、かつComparableHasher[X]ComparableHasher[Y]の間の変換もできないようにしている。

関連リンク