Last active
October 21, 2022 19:42
-
-
Save polosaty/60dd10cf9b4ae0a2e4eb91253c9c78c4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"hash" | |
"hash/fnv" | |
"log" | |
) | |
type Store struct { | |
count int | |
table []*Node | |
h64 hash.Hash64 | |
} | |
type Node struct { | |
Key string | |
Value int | |
Next *Node | |
} | |
func NewStore() *Store { | |
return &Store{ | |
table: make([]*Node, 1), | |
h64: fnv.New64a(), | |
} | |
} | |
func (s *Store) hash(key string) uint64 { | |
defer s.h64.Reset() | |
if _, err := s.h64.Write([]byte(key)); err != nil { | |
log.Println("hash of key: ", key, " raised error: ", err) | |
} | |
return s.h64.Sum64() % uint64(len(s.table)) | |
} | |
func NewNode(key string, value int, next *Node) *Node { | |
return &Node{ | |
key, value, next, | |
} | |
} | |
func (s *Store) put(key string, value int) { | |
j := s.hash(key) | |
for node := s.table[j]; node != nil; node = node.Next { | |
if key == node.Key { | |
node.Value = value | |
return | |
} | |
} | |
if s.count >= len(s.table) { | |
s.rehash() | |
j = s.hash(key) | |
} | |
s.table[j] = NewNode(key, value, s.table[j]) | |
s.count++ | |
} | |
func (s *Store) rehash() { | |
oldTable := s.table | |
s.table = make([]*Node, len(oldTable)*2) | |
s.count = 0 | |
for _, tab := range oldTable { | |
for node := tab; node != nil; node = node.Next { | |
s.put(node.Key, node.Value) | |
} | |
} | |
} | |
var NotFoundErr = errors.New("node not found") | |
func (s *Store) get(key string) (int, error) { | |
j := s.hash(key) | |
for node := s.table[j]; node != nil; node = node.Next { | |
if key == node.Key { | |
return node.Value, nil | |
} | |
} | |
return 0, NotFoundErr | |
} | |
func check(key string, value int, s *Store) { | |
v, err := s.get(key) | |
if err != nil { | |
log.Println("search key:", key, "err:", err) | |
return | |
} | |
if v == value { | |
log.Println(key, " is ok") | |
} else { | |
log.Println(key, " is broken") | |
} | |
} | |
func main() { | |
s := NewStore() | |
s.put("cat", 10) | |
s.put("dog", 20) | |
s.put("fox", 30) | |
s.put("art", 40) | |
s.put("car", 50) | |
s.put("cat", 60) | |
check("cat", 60, s) | |
check("dog", 20, s) | |
check("fox", 30, s) | |
check("art", 40, s) | |
check("car", 50, s) | |
check("crow", 0, s) // search key: crow err: node not found | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment