func (sm *StrMap) Range(f func(key string, value interface{}) bool) {
	for shard := range sm.mutexes {
		sm.mutexes[shard].RLock()
		for key, value := range sm.maps[shard] {
			if !f(key, value) {
				sm.mutexes[shard].RUnlock()
				return
			}
		}
		sm.mutexes[shard].RUnlock()
	}
}
Range is modeled after sync.Map.Range. It calls f sequentially for each key
and value present in each of the shards in the map. If f returns false, range
stops the iteration.

No key will be visited more than once, but if any value is inserted
concurrently, Range may or may not visit it. Similarly, if a value is
modified concurrently, Range may visit the previous or newest version of said
value.
package shardedmap
import (
	"sync"
)
type StrMap struct {
	shardCount uint64  
	mutexes    []sync.RWMutex
	maps       []map[string]interface{}
}
func NewStrMap(shardCount int) *StrMap {
	if shardCount <= 0 {
		shardCount = defaultShards
	}
	sm := &StrMap{
		shardCount: uint64(shardCount),
		mutexes:    make([]sync.RWMutex, shardCount),
		maps:       make([]map[string]interface{}, shardCount),
	}
	for i := range sm.maps {
		sm.maps[i] = make(map[string]interface{})
	}
	return sm
}
func (sm *StrMap) pickShard(key string) uint64 {
	return memHashString(key) % sm.shardCount
}
func (sm *StrMap) Store(key string, value interface{}) {
	shard := sm.pickShard(key)
	sm.mutexes[shard].Lock()
	sm.maps[shard][key] = value
	sm.mutexes[shard].Unlock()
}
func (sm *StrMap) Load(key string) (interface{}, bool) {
	shard := sm.pickShard(key)
	sm.mutexes[shard].RLock()
	value, ok := sm.maps[shard][key]
	sm.mutexes[shard].RUnlock()
	return value, ok
}
func (sm *StrMap) LoadOrStore(key string, value interface{}) (actual interface{}, loaded bool) {
	shard := sm.pickShard(key)
	sm.mutexes[shard].RLock()
	if actual, loaded = sm.maps[shard][key]; loaded {
		sm.mutexes[shard].RUnlock()
		return
	}
	sm.mutexes[shard].RUnlock()
	sm.mutexes[shard].Lock()
	if actual, loaded = sm.maps[shard][key]; loaded {
		sm.mutexes[shard].Unlock()
		return
	}
	sm.maps[shard][key] = value
	sm.mutexes[shard].Unlock()
	return value, loaded
}
func (sm *StrMap) Delete(key string) {
	shard := sm.pickShard(key)
	sm.mutexes[shard].Lock()
	delete(sm.maps[shard], key)
	sm.mutexes[shard].Unlock()
}