Skip to content

Instantly share code, notes, and snippets.

@zemirco
Last active October 8, 2022 09:58
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save zemirco/49e6bebd8f281bce349136931d939cad to your computer and use it in GitHub Desktop.
Save zemirco/49e6bebd8f281bce349136931d939cad to your computer and use it in GitHub Desktop.
golang database layer with cache
type CacheInterface interface {
Get(key string) ([]byte, error)
Set(key string, value interface{}) error
}
// Cache implements CacheInterface.
type Cache struct {
// wrap redis pool connection
// or whatever you need
}
func (c *Cache) Get(key string) ([]byte, error) {
// get data from redis
return b, nil
}
func (c *Cache) Set(key string, value interface{}) error {
// save data to redis
return nil
}
type DatabaseInterface interface {
GetFollowers(userID string) ([]models.User, error)
}
type Database struct {
// wrap sql connection
// or any other driver that your database needs
}
func (db *Database) GetFollowers(userID string) ([]models.User, error) {
// get users from db
// can be any db, e.g. PostgreSQL, CouchDB, MongoDB
return users, nil
}
// handler gets followers through database wrapper
// the wrapper checks the cache first and then checks the database
func(w http.ResponseWriter, r *http.Request) {
// get user from url
users, err := wrapper.GetFollowers(user.ID)
if err != nil {
// return err
}
// do something with users
}
// handler needs access to pure caching and/or database methods
func(w http.ResponseWriter, r *http.Request) {
cache := wrapper.GetCache()
// do something that cache provides but that the wrapper does not
b, err := cache.Get("some:key")
if err != nil {
// return err
}
// do something with b
}
type WrapperInterface interface {
GetFollowers(userID string) ([]models.User, error)
// sometimes I need access to the pure db and/or cache
GetCache() CacheInterface
GetDB() DatabaseInterface
}
// Wrapper implements WrapperInterface.
type Wrapper struct {
Cache CacheInterface
Database DatabaseInterface
}
func (w *Wrapper) GetCache() CacheInterface {
return w.Cache
}
func (w *Wrapper) GetDatabase() DatabaseInterface {
return w.Database
}
func (w *Wrapper) GetFollowers(userID string) ([]models.User, err) {
// check cache first
b, err := db.Cache.Get("key")
if err != nil && err != redis.ErrNil {
return nil, err
}
// if chache does not have any data get it from database
if err == redis.ErrNil {
data, err := db.Database.GetFollowers(userID)
if err != nil {
return nil, err
}
// add data to cache
if err := db.Cache.Set(key, result); err != nil {
return nil, err
}
return result, nil
}
// return data from cache
var result []models.User
if err := json.Unmarshal(b, &result); err != nil {
return nil, err
}
return result, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment