Logo

0x3d.Site

is designed for aggregating information.
Welcome
check repository here

gdcache

gdcache is a pure non-intrusive cache library implemented by golang, you can use it to implement your own cache. 中文文档

Go Report Card PkgGoDev codecov

Features

  • Automatically cache sql
  • Reuse id cache
  • Adapt to Xorm and Gorm framework
  • Support cache joint key
  • Lightweight
  • Non-invasive
  • High performance
  • Flexible

Core principle

The core principle of gdcache is to convert sql into id and cache it, and cache the entity corresponding to id. In this way, each sql has the same id and can reuse the corresponding entity content.

img.png

As shown in the figure above, each piece of sql can be converted to the corresponding sql, and the bottom layer will reuse these ids. If these ids are not queried, because we don’t know whether they are out of date or because these values do not exist in the database, we will all be in the database and access these entities that cannot be retrieved from the cache from the database. Get it once, and if it can get it, it will cache it once.

Save memory

The conventional caching framework will cache the content of the result, but the gdcache cache library is different from it. It will only cache the id of the result and find the value through the id. The advantage of this is that the value can be reused, and the value corresponding to id will only be cached once.

Installation

go get github.com/ulovecode/gdcache

Quick Start

  • The class to be cached must implement the TableName() method, and use cache:"id" to indicate the cached key. The default is to cache by id, and the value of the cache tag corresponds to Fields in the database, usually can be ignored.
type User struct {
    Id   uint64 `cache:"id"` // Or omit the tag
    Name string
    Age  int
}

func (u User) TableName() string {
    return "user"
}
  • If you want to use a joint key, you can add a cache tag to multiple fields
type PublicRelations struct {
    RelatedId uint64 `cache:"related_id"`
    RelatedType string
    SourceId uint64 `cache:"source_id"`
    SourceType string
}

func (u PublicRelations) TableName() string {
    return "public_relations"
}
  • Implement the ICache interface, you can use redis or gocache as the underlying implementation.
type MemoryCacheHandler struct {
    data map[string][]byte
}

func (m MemoryCacheHandler) StoreAll(keyValues ...gdcache.KeyValue) (err error) {
    for _, keyValue := range keyValues {
        m.data[keyValue.Key] = keyValue.Value
    }
    return nil
}

func (m MemoryCacheHandler) Get(key string) (data []byte, has bool, err error) {
    bytes, has := m.data[key]
    return bytes, has, nil
}

func (m MemoryCacheHandler) GetAll(keys schemas.PK) (data []gdcache.ReturnKeyValue, err error) {
    returnKeyValues := make([]gdcache.ReturnKeyValue, 0)
    for _, key := range keys {
        bytes, has := m.data[key]
        returnKeyValues = append(returnKeyValues, gdcache.ReturnKeyValue{
        KeyValue: gdcache.KeyValue{
        Key:   key,
        Value: bytes,
    },
        Has: has,
    })
}
    return returnKeyValues, nil
}

func (m MemoryCacheHandler) DeleteAll(keys schemas.PK) error {
    for _, k := range keys {
        delete(m.data, k)
    }
    return nil
}

func NewMemoryCacheHandler() *MemoryCacheHandler {
    return &MemoryCacheHandler{
    data: make(map[string][]byte, 0),
    }
}

Gorm usage

Implement the IDB interface

type GormDB struct {
    db *gorm.DB
}

func (g GormDB) GetEntries(entries interface{}, sql string) error {
    tx := g.db.Raw(sql).Find(entries)
    return tx.Error
}

func (g GormDB) GetEntry(entry interface{}, sql string) (bool, error) {
    tx := g.db.Raw(sql).Take(entry)
    if gorm.ErrRecordNotFound == tx.Error {
        return false, nil
    }
    return tx.Error != gorm.ErrRecordNotFound, tx.Error
}

func NewGormCacheHandler() *gdcache.CacheHandler {
    return gdcache.NewCacheHandler(NewMemoryCacheHandler(), NewGormDd())
}

func NewGormDd() gdcache.IDB {
    db, err := gorm.Open(mysql.Open("root:root@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True&loc=Local"), &gorm.Config{})
    if err != nil {
        panic(err)
    }
    return GormDB{
        db: db,
    }
}

Xorm usage

Implement the IDB interface

type XormDB struct {
    db *xorm.Engine
}

func (g XormDB) GetEntries(entries interface{}, sql string) ( error) {
    err := g.db.SQL(sql).Find(entries)
    return err
}

func (g XormDB) GetEntry(entry interface{}, sql string) ( bool, error) {
    has, err := g.db.SQL(sql).Get(entry)
    return has, err
}

func NewXormCacheHandler() *gdcache.CacheHandler {
    return gdcache.NewCacheHandler(NewMemoryCacheHandler(), NewXormDd())
}

func NewXormDd() gdcache.IDB {
    db, err := xorm.NewEngine("mysql", "root:root@/test?charset=utf8")
    if err != nil {
        panic(err)
    }
    return XormDB{
        db: db,
    }
}

Native SQL usage

Implement the IDB interface

type MemoryDb struct {
}

func NewMemoryDb() *MemoryDb {
    return &MemoryDb{}
}

func (m MemoryDb) GetEntries(entries interface{}, sql string) error {
    mockEntries := make([]MockEntry, 0)
    mockEntries = append(mockEntries, MockEntry{
    RelateId:   1,
    SourceId:   2,
    PropertyId: 3,
    })
    marshal, _ := json.Marshal(mockEntries)
    json.Unmarshal(marshal, entries)
    return nil
}

func (m MemoryDb) GetEntry(entry interface{}, sql string) (bool, error) {
    mockEntry := &MockEntry{
    RelateId:   1,
    SourceId:   2,
    PropertyId: 3,
    }
    marshal, _ := json.Marshal(mockEntry)
    json.Unmarshal(marshal, entry)
    return true, nil
}

func NewMemoryCache() *gdcache.CacheHandler {
    return gdcache.NewCacheHandler(NewMemoryCacheHandler(), NewMemoryDb())
}

How to use

When querying a single entity, query through the entity's id and fill it into the entity. When getting multiple entities, you can use any sql query and finally fill it into the entity. Both methods must be introduced into the body's pointer.

func TestNewGormCache(t *testing.T) {

    handler := NewGormCacheHandler()

    user := User{
        Id: 1,
    }
    has, err := handler.GetEntry(&user)
    if err != nil {
        t.FailNow()
    }
    if has {
        t.Logf("%v", user)
    }
    
    users := make([]User, 0)
    err = handler.GetEntries(&users, "SELECT * FROM user WHERE name = '33'")
    if err != nil {
        t.FailNow()
    }
    for _, user := range users {
        t.Logf("%v", user)
    }
    
    err = handler.GetEntries(&users, "SELECT * FROM user WHERE id in (3)")
    if err != nil {
        t.FailNow()
    }
    for _, user := range users {
        t.Logf("%v", user)
    }
    
    count, err = handler.GetEntriesAndCount(&users1, "SELECT * FROM user WHERE id in (1,2)")
    if err != nil {
        t.FailNow()
    }
    for _, user := range users1 {
        t.Logf("%v", user)
    }
    t.Log(count)
    }
    users3 := make([]User, 0)
    ids := make([]uint64, 0)
    count, err = handler.GetEntriesAndCount(&users3, "SELECT * FROM user WHERE id in ?", ids)
    if err != nil {
        t.FailNow()
    }
    for _, user := range users1 {
        t.Logf("%v", user)
    }
    t.Log(count)
    
    
    count, err = handler.GetEntriesAndCount(&users1, "SELECT * FROM user WHERE id =  ?", 1)
    if err != nil {
        t.FailNow()
    }
    for _, user := range users1 {
        t.Logf("%v", user)
    }
    t.Log(count)
    
    condition := []User{{Id:   1,},{Id:   2,},{Id:   3,}}
    
    err = handler.GetEntriesByIds(&users1, condition)
    if err != nil {
        t.FailNow()
    }
    for _, user := range users1 {
        t.Logf("%v", user)
    }
    t.Log(count)

Support placeholder ?, replacement arrays and basic types

Contributing

You can help provide better gdcahe by submitting pr.

License

© Jovanzhu, 2021~time.Now

Released under the MIT License

Golang
Golang
Golang, or Go, is a statically typed programming language developed by Google. It’s known for its simplicity, performance, and support for concurrent programming. Go is widely used in cloud computing, server-side applications, and microservices.
GitHub - goyek/goyek: Task automation Go library
GitHub - goyek/goyek: Task automation Go library
gommon/color at master · labstack/gommon
gommon/color at master · labstack/gommon
GitHub - blevesearch/bleve: A modern text/numeric/geo-spatial/vector indexing library for go
GitHub - blevesearch/bleve: A modern text/numeric/geo-spatial/vector indexing library for go
GitHub - schollz/progressbar: A really basic thread-safe progress bar for Golang applications
GitHub - schollz/progressbar: A really basic thread-safe progress bar for Golang applications
GitHub - free/concurrent-writer: Highly concurrent drop-in replacement for bufio.Writer
GitHub - free/concurrent-writer: Highly concurrent drop-in replacement for bufio.Writer
GitHub - mattn/go-colorable
GitHub - mattn/go-colorable
GitHub - StudioSol/set: A simple Set data structure implementation in Go (Golang) using LinkedHashMap.
GitHub - StudioSol/set: A simple Set data structure implementation in Go (Golang) using LinkedHashMap.
GitHub - essentialkaos/branca: Authenticated encrypted API tokens (IETF XChaCha20-Poly1305 AEAD) for Golang
GitHub - essentialkaos/branca: Authenticated encrypted API tokens (IETF XChaCha20-Poly1305 AEAD) for Golang
Cloud Native Computing Foundation
Cloud Native Computing Foundation
GitHub - sakirsensoy/genv: Genv is a library for Go (golang) that makes it easy to read and use environment variables in your projects. It also allows environment variables to be loaded from the .env file.
GitHub - sakirsensoy/genv: Genv is a library for Go (golang) that makes it easy to read and use environment variables in your projects. It also allows environment variables to be loaded from the .env file.
GitHub - heetch/confita: Load configuration in cascade from multiple backends into a struct
GitHub - heetch/confita: Load configuration in cascade from multiple backends into a struct
GitHub - brianvoe/sjwt: Simple JWT Golang
GitHub - brianvoe/sjwt: Simple JWT Golang
GitHub - subpop/go-ini: Go package that encodes and decodes INI-files
GitHub - subpop/go-ini: Go package that encodes and decodes INI-files
GitHub - DylanMeeus/GoAudio: Go tools for audio processing & creation 🎶
GitHub - DylanMeeus/GoAudio: Go tools for audio processing & creation 🎶
GitHub - daviddengcn/go-colortext: Change the color of console text.
GitHub - daviddengcn/go-colortext: Change the color of console text.
GitHub - andOTP/andOTP: [Unmaintained] Open source two-factor authentication for Android
GitHub - andOTP/andOTP: [Unmaintained] Open source two-factor authentication for Android
GitHub - alfiankan/crab-config-files-templating: Dynamic configuration file templating tool for kubernetes manifest or general configuration files
GitHub - alfiankan/crab-config-files-templating: Dynamic configuration file templating tool for kubernetes manifest or general configuration files
GitHub - viney-shih/go-cache: A flexible multi-layer Go caching library to deal with in-memory and shared cache by adopting Cache-Aside pattern.
GitHub - viney-shih/go-cache: A flexible multi-layer Go caching library to deal with in-memory and shared cache by adopting Cache-Aside pattern.
GitHub - TreyBastian/colourize: An ANSI colour terminal package for Go
GitHub - TreyBastian/colourize: An ANSI colour terminal package for Go
GitHub - Evertras/bubble-table: A customizable, interactive table component for the Bubble Tea framework
GitHub - Evertras/bubble-table: A customizable, interactive table component for the Bubble Tea framework
GitHub - deatil/go-array: A Go package that read or set data from map, slice or json
GitHub - deatil/go-array: A Go package that read or set data from map, slice or json
GitHub - cometbft/cometbft: CometBFT (fork of Tendermint Core): A distributed, Byzantine fault-tolerant, deterministic state machine replication engine
GitHub - cometbft/cometbft: CometBFT (fork of Tendermint Core): A distributed, Byzantine fault-tolerant, deterministic state machine replication engine
GitHub - icza/session: Go session management for web servers (including support for Google App Engine - GAE).
GitHub - icza/session: Go session management for web servers (including support for Google App Engine - GAE).
GitHub - cristalhq/jwt: Safe, simple and fast JSON Web Tokens for Go
GitHub - cristalhq/jwt: Safe, simple and fast JSON Web Tokens for Go
GitHub - lrita/cmap: a thread-safe concurrent map for go
GitHub - lrita/cmap: a thread-safe concurrent map for go
GitHub - wzshiming/ctc: Console Text Colors - The non-invasive cross-platform terminal color library does not need to modify the Print method
GitHub - wzshiming/ctc: Console Text Colors - The non-invasive cross-platform terminal color library does not need to modify the Print method
GitHub - goradd/maps: map library using Go generics that offers a standard interface, go routine synchronization, and sorting
GitHub - goradd/maps: map library using Go generics that offers a standard interface, go routine synchronization, and sorting
GitHub - alfiankan/teleterm: Telegram Bot Exec Terminal Command
GitHub - alfiankan/teleterm: Telegram Bot Exec Terminal Command
GitHub - JeremyLoy/config: 12 factor configuration as a typesafe struct in as little as two function calls
GitHub - JeremyLoy/config: 12 factor configuration as a typesafe struct in as little as two function calls
GitHub - goraz/onion: Layer based configuration for golang
GitHub - goraz/onion: Layer based configuration for golang
Golang
More on Golang

Programming Tips & Tricks

Code smarter, not harder—insider tips and tricks for developers.

Error Solutions

Turn frustration into progress—fix errors faster than ever.

Shortcuts

The art of speed—shortcuts to supercharge your workflow.
  1. Collections 😎
  2. Frequently Asked Question's 🤯

Tools

available to use.

Made with ❤️

to provide resources in various ares.