liveBook · Manning

Key-value store

As explained in Learn Go with Pocket-Sized Projects

Key-value storage is a data-storage model that associates each key with a corresponding value for retrieval by key.

A key-value store associates each key with a value and retrieves that value by key. In Go, a map provides the basic implementation. This model fits game data accessed by game ID and can also support a generic cache. section 8.4.1 section 7.1.3

A practical Go implementation makes these choices:

  • Constrain keys with comparable so the map can determine key equality. section 7.1.3
  • Parameterize both keys and values, such as integer keys and string values. section 7.1.3
  • Initialize the internal map through New, because an uninitialized map cannot be used safely. section 7.1.3
  • Hide the map behind cache operations such as Read, Upsert, and Delete instead of exposing it to clients. section 8.4.1 section 7.1.3

Games indexed by ID

A service can keep its games in a map keyed by game ID. Clients call the service API rather than accessing the database package directly, leaving room for security, events, or leaderboard logic. A reusable cache applies the same pattern to arbitrary comparable keys and values. section 8.4.1 section 7.1.3

Listing 7.1 cache.go
// Cache is key-value storage.
type Cache[K comparable, V any] struct {
    data  map[K]V
}

Inspect the generic Cache structure, which stores parameterized values in a map keyed by comparable types. section 7.1.3

Listing 7.2 cache.go
// New creates a usable Cache.
func New[K comparable, V any]() Cache[K, V] {
    return Cache[K, V]{
        data: make(map[K]V),
    }
}

Inspect the constructor that creates a usable cache by initializing its internal map. section 7.1.3

Listing 7.3 cache.go: Implementing the Read method on the cache
// Read returns the associated value for a key,
// and a boolean to true if the key is absent.
func (c *Cache[K, V]) Read(key K) (V, bool) {
    v, found := c.data[key]
    return v, found
}

Inspect Read, which returns the value associated with a key together with a presence boolean. section 7.1.3

Listing 7.4 cache.go: Implementing the Upsert function on the cache
// Upsert overrides the value for a given key.
func (c *Cache[K, V]) Upsert(key K, value V) error {
    c.data[key] = value

    // Do not return an error for the moment,
    // but it can happen in the near future.
    return nil
}

Inspect Upsert, which replaces the value stored for a key. section 7.1.3

Listing 7.5 cache.go: Implementing the Delete method on the cache
// Delete removes the entry for the given key.
func (c *Cache[K, V]) Delete(key K) {    
    delete(c.data, key)
}

Inspect Delete, which removes the entry associated with a key. section 7.1.3

How Learn Go with Pocket-Sized Projects covers it

How deep it goes
Explains map representation, generic constraints, initialization, value ownership, and basic operations, stopping short of persistent storage.
Examples
Demonstrates games keyed by IDs, integer-to-string tests, and a generic Cache with Read, Upsert, and Delete methods.
What it assumes
Assumes Go familiarity while reinforcing maps, generic type parameters, comparable constraints, and map initialization.
What you can do after
Build a generic in-memory cache with comparable keys, initialized maps, and controlled read, update, and delete operations.
How it connects
Connects key-value stores to Go maps, generics, caches, constructors, encapsulation, service APIs, and in-memory databases.

Also explained in

Compare how 8 books explain key-value store →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Go with Pocket-Sized Projects. The section links point to the parts of the book it draws on.