-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
213 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
# mcache | ||
|
||
`mcache` is a simple and thread-safe in-memory cache library for Go. | ||
|
||
## Features | ||
|
||
- Thread-safe cache operations | ||
- Set key-value pairs with optional expiration time | ||
- Get values by key | ||
- Check if a key exists | ||
- Delete key-value pairs | ||
- Clear the entire cache | ||
- Cleanup expired key-value pairs | ||
|
||
## Installation | ||
|
||
Use `go get` to install the package: | ||
|
||
```shell | ||
go get github.com/parMaster/mcache | ||
``` | ||
|
||
## Usage | ||
|
||
Import the `mcache` package in your Go code: | ||
|
||
```go | ||
import "github.com/parMaster/mcache" | ||
``` | ||
|
||
Create a new cache instance using the `NewCache` constructor: | ||
|
||
```go | ||
cache := mcache.NewCache() | ||
``` | ||
|
||
### Set | ||
|
||
Set a key-value pair in the cache. The key must be a string, and the value can be any type that implements the `interface{}` interface, ttl is int64 value in seconds: | ||
|
||
```go | ||
err := cache.Set("key", "value", 0) | ||
if err != nil { | ||
// handle error | ||
} | ||
``` | ||
|
||
If the key already exists and is not expired, an error `mcache.ErrKeyExists` will be returned. If the key exists but is expired, the value will be updated. | ||
|
||
You can also set a key-value pair with an expiration time (in seconds): | ||
|
||
```go | ||
err := cache.Set("key", "value", 60) | ||
if err != nil { | ||
// handle error | ||
} | ||
``` | ||
|
||
The value will automatically expire after the specified duration. | ||
|
||
_Note that int64 is used instead of time.Duration for the expiration time. This choise is deliberate to simplify the API. It can be changed in the future, I can break the API but only in the next major version._ | ||
|
||
### Get | ||
|
||
Retrieve a value from the cache by key: | ||
|
||
```go | ||
value, err := cache.Get("key") | ||
if err != nil { | ||
// handle error | ||
} | ||
``` | ||
|
||
If the key does not exist, an error `mcache.ErrKeyNotFound` will be returned. If the key exists but is expired, an error `mcache.ErrExpired` will be returned, and the key-value pair will be deleted. | ||
|
||
Either error or value could be checked to determine if the key exists. | ||
|
||
### Has | ||
|
||
Check if a key exists in the cache: | ||
|
||
```go | ||
exists, err := cache.Has("key") | ||
if err != nil { | ||
// handle error | ||
} | ||
|
||
if exists { | ||
// key exists | ||
} else { | ||
// key does not exist | ||
} | ||
``` | ||
|
||
If the key exists but is expired, an error `mcache.ErrExpired` will be returned, and the key-value pair will be deleted. | ||
|
||
### Delete | ||
|
||
Delete a key-value pair from the cache: | ||
|
||
```go | ||
err := cache.Del("key") | ||
if err != nil { | ||
// handle error | ||
} | ||
``` | ||
|
||
### Clear | ||
|
||
Clear the entire cache: | ||
|
||
```go | ||
err := cache.Clear() | ||
if err != nil { | ||
// handle error | ||
} | ||
``` | ||
|
||
### Cleanup | ||
|
||
Cleanup expired key-value pairs in the cache. You can call this method periodically to remove expired key-value pairs from the cache: | ||
|
||
```go | ||
cache.Cleanup() | ||
``` | ||
|
||
## Examples | ||
|
||
See the [examples](https://github.com/parMaster/mcache/examples) directory for more examples. | ||
|
||
## Contributing | ||
|
||
Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request. | ||
|
||
## License | ||
|
||
This project is licensed under the [GNU GPLv3](https://choosealicense.com/licenses/gpl-3.0/) license. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/parMaster/mcache" | ||
) | ||
|
||
func demo() { | ||
|
||
fmt.Println("\r\n Demo 1:") | ||
fmt.Println("------------------------------------------------------------") | ||
|
||
cache := mcache.NewCache() | ||
|
||
cache.Set("save indefinitely", "value without expiration", 0) // set value without expiration | ||
cache.Set("save for 1 second", "value will expire in 1 second", 1) // set value with expiration in 1 second | ||
|
||
exists, err := cache.Has("no such key") | ||
// either exists or error can be checked | ||
if err != nil { | ||
// possible errors: | ||
// mcache.ErrKeyNotFound | ||
// mcache.ErrExpired | ||
fmt.Println(err) | ||
} | ||
if !exists { | ||
fmt.Println("key doen't exist or expired") | ||
} | ||
|
||
v, _ := cache.Get("save indefinitely") | ||
fmt.Println(v) | ||
|
||
time.Sleep(1 * time.Second) | ||
v, _ = cache.Get("save for 1 second") | ||
fmt.Println(v) // <nil> because key expired | ||
|
||
} | ||
|
||
func main() { | ||
demo() | ||
demo_hit_or_miss() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/parMaster/mcache" | ||
) | ||
|
||
func expensive_func() interface{} { | ||
time.Sleep(1 * time.Second) | ||
return "expensive result" | ||
} | ||
|
||
func demo_hit_or_miss() { | ||
fmt.Println("\r\n Hit or Miss:") | ||
fmt.Println("------------------------------------------------------------") | ||
|
||
cache := mcache.NewCache() | ||
// expensive_func will be called only once | ||
// because result will be saved in cache | ||
for i := 0; i < 10; i++ { | ||
v, err := cache.Get("expensive value") | ||
if err != nil { | ||
fmt.Println("cache miss, calling expensive_func") | ||
v = expensive_func() | ||
cache.Set("expensive value", v, 0) | ||
continue | ||
} | ||
fmt.Println("cache hit - " + v.(string)) | ||
} | ||
} |