#!/usr/bin/env bash
set -euo pipefail
mkdir -p internal/cache cmd/serve
cat > go.mod <<'EOF'
module svc
go 1.22
EOF
cat > internal/cache/cache.go <<'EOF'
package cache
import "time"
// Cache is a tiny expiring key-value store.
type Cache struct {
ttl time.Duration
maxSize int
entries map[string]entry
}
type entry struct {
value string
expires time.Time
}
// New builds a Cache. The maxSize parameter was added when eviction landed.
func New(ttl time.Duration, maxSize int) *Cache {
return &Cache{ttl: ttl, maxSize: maxSize, entries: map[string]entry{}}
}
func (c *Cache) Set(k, v string) {
if len(c.entries) >= c.maxSize {
for key := range c.entries {
delete(c.entries, key)
break
}
}
c.entries[k] = entry{value: v, expires: time.Now().Add(c.ttl)}
}
func (c *Cache) Get(k string) (string, bool) {
e, ok := c.entries[k]
if !ok || time.Now().After(e.expires) {
return "", false
}
return e.value, true
}
EOF
cat > cmd/serve/main.go <<'EOF'
package main
import (
"fmt"
"time"
"svc/internal/cache"
)
func main() {
c := cache.New(5 * time.Minute)
c.Set("greeting", "hello")
v, ok := c.Get("greeting")
fmt.Println(v, ok)
}
EOF
cat > internal/cache/cache_test.go <<'EOF'
package cache
import (
"testing"
"time"
)
func TestSetGet(t *testing.T) {
c := New(time.Minute, 10)
c.Set("k", "v")
if got, ok := c.Get("k"); !ok || got != "v" {
t.Errorf("Get() = %q, %v", got, ok)
}
}
EOF
git init -q . && git add -A && git -c user.email=e@x -c user.name=n commit -qm base