How to Implement a Hash Map from Scratch in Go

Implement a Go hash map by defining a struct with a bucket slice, using maphash for key hashing, and handling collisions via chaining.

Implement a hash map in Go by defining a struct with a slice of buckets, a hash function, and methods for insertion and retrieval. Use maphash.Hasher for hashing keys and handle collisions with chaining.

package main

import (
	"crypto/rand"
	"hash/maphash"
)

type HashMap[K comparable, V any] struct {
	buckets []*bucket
	size    int
	hasher  maphash.Hasher
}

type bucket struct {
	key K
	val V
	next *bucket
}

func NewHashMap[K comparable, V any]() *HashMap[K, V] {
	var seed [32]byte
	rand.Read(seed[:])
	return &HashMap[K, V]{
		buckets: make([]*bucket, 16),
		hasher:  maphash.New(seed),
	}
}

func (m *HashMap[K, V]) Put(key K, val V) {
	m.hasher.Reset()
	// Note: In production, use a custom hash for K or reflect
	// This is a simplified example assuming K is hashable via maphash
	// For a real implementation, you'd need to hash the key bytes.
	// Here we assume a generic hash function is available for K.
	// For simplicity, this example uses a placeholder logic.
	// Real implementation requires converting K to []byte or using a custom hasher.
	// Assuming a working hash function h(key) returns uint64:
	// idx := h(key) % uint64(len(m.buckets))
	// ... insert logic ...
}

func (m *HashMap[K, V]) Get(key K) (V, bool) {
	// Similar logic to Put, find bucket, traverse chain
	var zero V
	return zero, false
}

Note: The code above is a structural skeleton. A production-ready implementation requires a robust way to hash generic keys K into bytes for maphash, often using unsafe or reflection, and full collision handling logic.