gocache is a small, educational Redis-like in-memory cache server implemented in Go. It implements a subset of the Redis protocol (RESP) and supports a few basic commands (PING, SET, GET, HSET, HGET, HGETALL). The project also includes an append-only file (AOF) persistence helper and a RESP parser/writer.
This project is intended as a learning implementation to demonstrate how a simple RESP server, command handlers, and persistent AOF logging can be structured in Go.
- RESP (REdis Serialization Protocol) parser and writer
 - Basic commands: 
PING,SET,GET,HSET,HGET,HGETALL - In-memory stores for simple keys and hash maps
 - Append-only file (AOF) writer and reader for simple persistence
 - Concurrency-safe access to the in-memory stores using RWMutex
 
resp.go- RESP parser and writer (reading and writing RESP values, marshalling/unmarshalling). It providesValue,Resp, andWritertypes.handler.go- Command handlers for supported commands, and in-memory maps with mutexes.aof.go- Append-only file helper that writes marshalled RESP entries to disk and can replay them.main.go- (entry point) expected to wire up the TCP listener, accept connections and use RESP, handlers and AOF. (See code for exact behavior.)
gocache implements a subset of RESP and models values with a Value type. The important RESP types used are:
- Bulk strings (prefixed by 
$) — used for keys and values - Arrays (prefixed by 
*) — used for commands and multi-part responses 
The repository includes helper methods to Marshal and Read these types from streams.
Example of the RAW RESP for the command SET mykey myvalue:
*3
$3
SET
$5
mykey
$7
myvalue
Requirements: Go 1.20+ (any modern Go should work).
Build the binary:
go build -o gocacheRun it (if main.go listens on a port, run the binary; otherwise use go run during development):
go run .
# or
./gocacheCheck main.go for the port and listen logic used by this repository. If main.go binds a port (for example :6379), you can connect with redis-cli -p 6379 or with nc/telnet and speak RESP manually.
redis-demo.mp4
The aof.go file provides an Aof struct which opens a file, writes marshalled Value entries, and periodically syncs the file to disk. The Aof writer uses a mutex to make writes safe across goroutines. The Read method allows replaying the file by invoking a callback for each recorded Value.
This AOF implementation is intentionally simple:
- It writes the RESP-marshalled bytes directly.
 - It periodically (every second) calls 
file.Sync()from a background goroutine. - It uses a single mutex for file operations.
 
On startup you can replay the AOF to restore the state by reading each recorded command and re-executing it against the in-memory handlers.
- The in-memory maps are protected with 
sync.RWMutexfor safe concurrent reads and writes. - The AOF uses a 
sync.Mutexfor serializing file writes and Sync calls. 
- Protocol: The RESP implementation is minimal (supports arrays and bulk strings primarily). Some RESP types and error handling are simplified.
 - Commands: Only a small subset of Redis commands are implemented.
 - Persistence: The AOF is naive and appends entire RESP frames. There is no rewriting/compaction.
 - Robustness: Error handling and malformed-resp handling can be improved.
 - Tests: Add unit tests for RESP parsing, handlers, and AOF replay.
 
Feel free to open issues or PRs. This project is intended for learning and exploration: improvements, refactors and test coverage are welcome.
This repository includes a LICENSE file — respect its terms when using or contributing.