### Install go-cache Source: https://github.com/viney-shih/go-cache/blob/master/README.md This snippet shows the command to install the go-cache library using go get. It is a direct dependency installation for your Go project. ```sh go get github.com/viney-shih/go-cache ``` -------------------------------- ### Basic Set and Get Operations in Go Source: https://github.com/viney-shih/go-cache/blob/master/README.md Illustrates the basic usage of the go-cache library for setting and getting key-value pairs. It showcases creating a cache group with specific settings like TTL and prefix, and handling cache misses. ```go type Object struct { Str string Num int } func Example_setAndGetPattern() { // We create a group of cache named "set-and-get". // It uses the shared cache only. Each key will be expired within ten seconds. c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "set-and-get", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: 10 * time.Second}, }, }, }) ctx := context.TODO() // set the cache obj := &Object{ Str: "value1", Num: 1, } if err := c.Set(ctx, "set-and-get", "key", obj); err != nil { panic("not expected") } // read the cache container := &Object{} if err := c.Get(ctx, "set-and-get", "key", container); err != nil { panic("not expected") } fmt.Println(container) // Output: Object{ Str: "value1", Num: 1} // read the cache but failed if err := c.Get(ctx, "set-and-get", "no-such-key", container); err != nil { fmt.Println(err) // Output: errors.New("cache key is missing") } // Output: // &{value1 1} // cache key is missing } ``` -------------------------------- ### Perform Basic Set and Get Operations using Shared Cache Source: https://context7.com/viney-shih/go-cache/llms.txt This example illustrates basic cache operations (Set and Get) using only the shared Redis cache. It configures a cache group named 'set-and-get' with a 10-second TTL for the shared cache. The code demonstrates setting an object, retrieving it successfully, and handling a cache miss scenario. ```go package main import ( "context" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) type Object struct { Str string Num int } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheFactory := cache.NewFactory(rds, tinyLfu) // Create cache group "set-and-get" with shared cache only, 10s TTL c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "set-and-get", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: 10 * time.Second}, }, }, }) ctx := context.TODO() // Set cache obj := &Object{Str: "value1", Num: 1} if err := c.Set(ctx, "set-and-get", "key", obj); err != nil { fmt.Printf("Error setting cache: %v\n", err) return } // Get cache - success container := &Object{} if err := c.Get(ctx, "set-and-get", "key", container); err != nil { fmt.Printf("Error getting cache: %v\n", err) return } fmt.Printf("Retrieved: %+v\n", container) // Output: &{value1 1} // Get cache - miss if err := c.Get(ctx, "set-and-get", "no-such-key", container); err != nil { fmt.Printf("Cache miss: %v\n", err) // Output: cache key is missing } } ``` -------------------------------- ### Implement Cache Filling with MGetter in Go Source: https://github.com/viney-shih/go-cache/blob/master/README.md The MGetter approach provides an alternative for cache filling. It's configured during the registration of cache settings and allows for fetching multiple keys at once when a cache miss occurs. This example demonstrates its use with both shared and local caches, each having a different TTL, and uses standard marshaling. ```go func ExampleService_Create_mGetter() { // We create a group of cache named "mgetter". // It uses both shared and local caches with separated TTL of one hour and ten minutes. c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "mgetter", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, MGetter: func(keys ...string) (interface{}, error) { // The MGetter is used to generate data when cache missed, and refill the cache automatically.. // You can read from DB or other microservices. // Assume we read from MySQL according to the key "key3" and get the value of Object{Str: "value3", Num: 3} // HINT: remember to return as a slice, and the item order needs to consist with the keys in the parameters. return []Object{{Str: "value3", Num: 3}}, nil }, MarshalFunc: cache.Marshal, UnmarshalFunc: cache.Unmarshal, }, }) ctx := context.TODO() container3 := &Object{} if err := c.Get(ctx, "mgetter", "key3", container3); err != nil { panic("not expected") } fmt.Println(container3) // Object{ Str: "value3", Num: 3} // Output: // &{value3 3} } ``` -------------------------------- ### Distributed Cache Invalidation with Pub-Sub in Go Source: https://context7.com/viney-shih/go-cache/llms.txt Explains how to maintain cache consistency across distributed systems using Redis Pub-Sub with the go-cache library. This feature enables cache invalidation signals to be broadcasted to all connected instances when an item is deleted. It requires 'github.com/go-redis/redis/v8' and 'github.com/viney-shih/go-cache'. The example demonstrates setting, getting, and deleting a cache entry, highlighting the automatic broadcast of the delete operation. ```go package main import ( "context" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) type Person struct { FirstName string LastName string Age int } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) // Enable Pub-Sub for distributed cache invalidation cacheFactory := cache.NewFactory(rds, tinyLfu, cache.WithPubSub(rds)) defer cacheFactory.Close() c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "user", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, }, }) ctx := context.TODO() // Set cache user := &Person{FirstName: "Tony", LastName: "Stock", Age: 87} if err := c.Set(ctx, "user", "tony", user); err != nil { fmt.Printf("Error: %v\n", err) return } // Get cache retrievedUser := &Person{} if err := c.Get(ctx, "user", "tony", retrievedUser); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("User: %+v\n", retrievedUser) // Output: &{Tony Stock 87} // Delete cache - broadcasts eviction to all instances via Pub-Sub if err := c.Del(ctx, "user", "tony"); err != nil { fmt.Printf("Error deleting: %v\n", err) return } fmt.Println("Cache deleted and eviction broadcasted to all instances") // All distributed instances will have their local cache invalidated } ``` -------------------------------- ### Custom Serialization with go-cache Source: https://context7.com/viney-shih/go-cache/llms.txt This Go code demonstrates how to configure go-cache to use custom serialization functions like MessagePack and JSON. It shows setting default marshal/unmarshal functions at the factory level and overriding them for specific cache instances based on their prefixes. The example includes storing and retrieving data using different serialization formats. ```go package main import ( "context" "encoding/json" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/vmihailenco/msgpack/v5" "github.com/viney-shih/go-cache" ) type CustomData struct { ID int Timestamp time.Time Data map[string]interface{}, } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) // Option 1: Set default marshal/unmarshal for all caches in factory cacheFactory := cache.NewFactory( rds, tinyLfu, cache.WithMarshalFunc(msgpack.Marshal), cache.WithUnmarshalFunc(msgpack.Unmarshal), ) // Option 2: Override per cache setting c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "json-cache", CacheAttributes: map[cache.Type]cache.Attribute{ cache.LocalCacheType: {TTL: 10 * time.Minute}, }, // Use JSON for this specific cache group MarshalFunc: json.Marshal, UnmarshalFunc: json.Unmarshal, }, { Prefix: "msgpack-cache", CacheAttributes: map[cache.Type]cache.Attribute{ cache.LocalCacheType: {TTL: 10 * time.Minute}, }, // Use built-in Marshal (msgpack + s2 compression) MarshalFunc: cache.Marshal, UnmarshalFunc: cache.Unmarshal, }, }) ctx := context.TODO() // Store with JSON serialization data1 := CustomData{ ID: 1, Timestamp: time.Now(), Data: map[string]interface{}{"key": "value"}, } if err := c.Set(ctx, "json-cache", "data1", data1); err != nil { fmt.Printf("Error: %v\n", err) return } // Store with msgpack+compression serialization data2 := CustomData{ ID: 2, Timestamp: time.Now(), Data: map[string]interface{}{"key": "value"}, } if err := c.Set(ctx, "msgpack-cache", "data2", data2); err != nil { fmt.Printf("Error: %v\n", err) return } // Retrieve retrieved1 := &CustomData{} c.Get(ctx, "json-cache", "data1", retrieved1) fmt.Printf("JSON cache: %+v\n", retrieved1) retrieved2 := &CustomData{} c.Get(ctx, "msgpack-cache", "data2", retrieved2) fmt.Printf("MsgPack cache: %+v\n", retrieved2) } ``` -------------------------------- ### Initialize Cache Factory Source: https://github.com/viney-shih/go-cache/blob/master/README.md Demonstrates how to initialize the cache factory using different caching backends like TinyLFU and Redis. The factory pattern is used to manage and provide cache instances. ```go // Initialize the Factory in main.go tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheFactory := cache.NewFactory(rds, tinyLfu) ``` -------------------------------- ### Multi-Layered Caching with Multiple Prefixes in Go Source: https://context7.com/viney-shih/go-cache/llms.txt Demonstrates creating multiple cache groups with different configurations and serialization methods using go-cache. It shows how to define separate settings for different data types (e.g., 'teacher' and 'student'), specifying cache attributes like TTL and custom marshaling functions (msgpack for teachers, built-in with compression for students). Dependencies include 'github.com/go-redis/redis/v8', 'github.com/vmihailenco/msgpack/v5', and 'github.com/viney-shih/go-cache'. ```go package main import ( "context" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/vmihailenco/msgpack/v5" "github.com/viney-shih/go-cache" ) type Person struct { FirstName string LastName string Age int } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheFactory := cache.NewFactory(rds, tinyLfu) // Create cache with multiple prefix groups - different configs for different entities c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "teacher", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, // Use msgpack for teacher data MarshalFunc: msgpack.Marshal, UnmarshalFunc: msgpack.Unmarshal, }, { Prefix: "student", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, MGetter: func(keys ...string) (interface{}, error) { // Database lookup for students results := make([]Person, len(keys)) for i, key := range keys { if key == "jacky" { results[i] = Person{FirstName: "Jacky", LastName: "Lin", Age: 38} } else { results[i] = Person{FirstName: "Unknown", LastName: "Unknown", Age: 0} } } return results, nil }, // Use built-in marshal with compression for student data MarshalFunc: cache.Marshal, UnmarshalFunc: cache.Unmarshal, }, }) ctx := context.TODO() // Get teacher data using GetByFunc teacher := &Person{} err := c.GetByFunc(ctx, "teacher", "jacky", teacher, func() (interface{}, error) { return Person{FirstName: "Jacky", LastName: "Wang", Age: 83}, nil }) if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Teacher: %+v\n", teacher) // Output: &{Jacky Wang 83} // Get student data using MGetter student := &Person{} if err := c.Get(ctx, "student", "jacky", student); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Student: %+v\n", student) // Output: &{Jacky Lin 38} } ``` -------------------------------- ### Initialize Factory with Redis and TinyLFU Adapters Source: https://context7.com/viney-shih/go-cache/llms.txt This snippet demonstrates how to initialize a go-cache factory with both a Redis adapter for shared caching and a TinyLFU adapter for in-memory caching. It configures the TinyLFU with a specified capacity and sets up the Redis client. The factory is then created, intended for singleton use. ```go package main import ( "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) func main() { // Initialize TinyLFU for in-memory cache with 10,000 key capacity tinyLfu := cache.NewTinyLFU(10000) // Initialize Redis for shared cache rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) // Create factory - use singleton pattern, initialize once in main.go cacheFactory := cache.NewFactory(rds, tinyLfu) defer cacheFactory.Close() // Factory is ready to create cache instances for different business logic } ``` -------------------------------- ### Batch Operations with MSet and MGet in Go Source: https://context7.com/viney-shih/go-cache/llms.txt Demonstrates how to efficiently set and retrieve multiple key-value pairs using MSet and MGet methods in the go-cache library. It initializes a cache with both local and shared cache configurations and performs batch operations, handling potential errors. ```Go package main import ( "context" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) type Product struct { ID string Name string Price float64 } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheFactory := cache.NewFactory(rds, tinyLfu) c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "product", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, }, }) ctx := context.TODO() // MSet - batch set multiple key-value pairs products := map[string]interface{}{ "prod1": Product{ID: "prod1", Name: "Laptop", Price: 999.99}, "prod2": Product{ID: "prod2", Name: "Mouse", Price: 29.99}, "prod3": Product{ID: "prod3", Name: "Keyboard", Price: 79.99}, } if err := c.MSet(ctx, "product", products); err != nil { fmt.Printf("Error in MSet: %v\n", err) return } fmt.Println("Batch set completed") // MGet - batch retrieve multiple keys result, err := c.MGet(ctx, "product", "prod1", "prod2", "prod3", "prod4") if err != nil { fmt.Printf("Error in MGet: %v\n", err) return } // Iterate through results for i := 0; i < result.Len(); i++ { product := &Product{} if err := result.Get(ctx, i, product); err != nil { fmt.Printf("Key at index %d not found: %v\n", i, err) continue } fmt.Printf("Product %d: %+v\n", i, product) } // Delete multiple keys if err := c.Del(ctx, "product", "prod1", "prod2", "prod3"); err != nil { fmt.Printf("Error deleting: %v\n", err) return } fmt.Println("Batch delete completed") } ``` -------------------------------- ### Monitoring Cache Performance with Callbacks in Go Source: https://context7.com/viney-shih/go-cache/llms.txt Illustrates how to integrate callback functions into the go-cache factory to monitor cache hits, misses, and local cache memory usage. This allows for real-time performance tracking and analysis of cache behavior. ```Go package main import ( "context" "fmt" "sync/atomic" "time" "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) type Metrics struct { hits int64 misses int64 localBytes int64 } func main() { metrics := &Metrics{} tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) // Create factory with callback functions for monitoring cacheFactory := cache.NewFactory( rds, tinyLfu, cache.OnCacheHitFunc(func(prefix, key string, count int) { atomic.AddInt64(&metrics.hits, int64(count)) fmt.Printf("Cache HIT: prefix=%s key=%s count=%d\n", prefix, key, count) }), cache.OnCacheMissFunc(func(prefix, key string, count int) { atomic.AddInt64(&metrics.misses, int64(count)) fmt.Printf("Cache MISS: prefix=%s key=%s count=%d\n", prefix, key, count) }), cache.OnLocalCacheCostAddFunc(func(prefix, key string, cost int) { atomic.AddInt64(&metrics.localBytes, int64(cost)) fmt.Printf("Local cache ADD: prefix=%s key=%s bytes=%d\n", prefix, key, cost) }), cache.OnLocalCacheCostEvictFunc(func(prefix, key string, cost int) { atomic.AddInt64(&metrics.localBytes, -int64(cost)) fmt.Printf("Local cache EVICT: prefix=%s key=%s bytes=%d\n", prefix, key, cost) }), ) c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "metrics-test", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, }, }) ctx := context.TODO() // First access - cache miss value := "" c.GetByFunc(ctx, "metrics-test", "key1", &value, func() (interface{}, error) { return "test-value", nil }) // Second access - cache hit c.Get(ctx, "metrics-test", "key1", &value) // Print metrics hitRate := float64(atomic.LoadInt64(&metrics.hits)) / float64(atomic.LoadInt64(&metrics.hits)+atomic.LoadInt64(&metrics.misses)) * 100 fmt.Printf("\nMetrics Summary:\n") fmt.Printf(" Hits: %d\n", atomic.LoadInt64(&metrics.hits)) fmt.Printf(" Misses: %d\n", atomic.LoadInt64(&metrics.misses)) fmt.Printf(" Hit Rate: %.2f%%\n", hitRate) fmt.Printf(" Local Cache Usage: %d bytes\n", atomic.LoadInt64(&metrics.localBytes)) } ``` -------------------------------- ### Cache-Aside with MGetter in Go Source: https://context7.com/viney-shih/go-cache/llms.txt Demonstrates the Cache-Aside pattern using MGetter, which allows configuring a batch getter function at cache creation time for efficient, automatic cache refills. This is ideal for retrieving multiple related data items at once. It relies on 'go-redis/redis/v8' and 'viney-shih/go-cache'. ```go package main import ( "context" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) type Object struct { Str string Num int } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheFactory := cache.NewFactory(rds, tinyLfu) // Create cache with both shared and local caches, with MGetter c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "mgetter", CacheAttributes: map[cache.Type]cache.Attribute{ cache.SharedCacheType: {TTL: time.Hour}, cache.LocalCacheType: {TTL: 10 * time.Minute}, }, // MGetter handles multiple keys at once MGetter: func(keys ...string) (interface{}, error) { // Called on cache miss - fetch from database // IMPORTANT: Return slice with same length and order as keys fmt.Printf("Fetching keys from database: %v\n", keys) results := make([]Object, len(keys)) for i, key := range keys { // Simulate database lookup results[i] = Object{Str: fmt.Sprintf("value%d", i+3), Num: i + 3} } return results, nil }, MarshalFunc: cache.Marshal, // Uses msgpack + compression UnmarshalFunc: cache.Unmarshal, }, }) ctx := context.TODO() // Get single key - MGetter called automatically on miss container := &Object{} if err := c.Get(ctx, "mgetter", "key3", container); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Retrieved: %+v\n", container) // Output: &{value3 3} // MGet multiple keys - efficient batch retrieval result, err := c.MGet(ctx, "mgetter", "key4", "key5", "key6") if err != nil { fmt.Printf("Error: %v\n", err) return } for i := 0; i < result.Len(); i++ { obj := &Object{} if err := result.Get(ctx, i, obj); err != nil { fmt.Printf("Error at index %d: %v\n", i, err) continue } fmt.Printf("Index %d: %+v\n", i, obj) } } ``` -------------------------------- ### Evict Cache Key Sequence Diagram Source: https://github.com/viney-shih/go-cache/blob/master/README.md Visualizes the process of evicting a cache key using the go-cache library. It shows the interaction between the Application, go-cache, Local Cache, Shared Cache, and PubSub components. ```mermaid sequenceDiagram participant APP as Application participant M as go-cache participant L as Local Cache participant S as Shared Cache participant PS as PubSub APP ->> M: Cache.Del() M ->> S: Adapter.Del() S -->> M: return error if necessary M ->> L: Adapter.Del() L -->> M: return error if necessary M ->> PS: Pubsub.Pub() (broadcast key eviction) M -->> APP: return nil or error ``` -------------------------------- ### Implement Cache Filling with GetByFunc in Go Source: https://github.com/viney-shih/go-cache/blob/master/README.md The GetByFunc method simplifies cache management by allowing you to provide a getter function. This function is automatically called to refill the cache when a cache miss occurs. It supports custom cache settings including local cache with specified TTL and message pack serialization. ```go func ExampleCache_GetByFunc() { // We create a group of cache named "get-by-func". // It uses the local cache only with TTL of ten minutes. c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "get-by-func", CacheAttributes: map[cache.Type]cache.Attribute{ cache.LocalCacheType: {TTL: 10 * time.Minute}, }, MarshalFunc: msgpack.Marshal, // msgpack is from "github.com/vmihailenco/msgpack/v5" UnmarshalFunc: msgpack.Unmarshal, }, }) ctx := context.TODO() container2 := &Object{} if err := c.GetByFunc(ctx, "get-by-func", "key2", container2, func() (interface{}, error) { // The getter is used to generate data when cache missed, and refill the cache automatically.. // You can read from DB or other microservices. // Assume we read from MySQL according to the key "key2" and get the value of Object{Str: "value2", Num: 2} return Object{Str: "value2", Num: 2}, nil }); err != nil { panic("not expected") } fmt.Println(container2) // Object{ Str: "value2", Num: 2} // Output: // &{value2 2} } ``` -------------------------------- ### Cache-Aside with GetByFunc in Go Source: https://context7.com/viney-shih/go-cache/llms.txt Implements the Cache-Aside pattern where a getter function is automatically called on a cache miss to populate the cache. This approach is suitable for fetching single data items. It requires the 'go-redis/redis/v8' and 'viney-shih/go-cache' libraries. ```go package main import ( "context" "fmt" "time" "github.com/go-redis/redis/v8" "github.com/viney-shih/go-cache" ) type Object struct { Str string Num int } func main() { tinyLfu := cache.NewTinyLFU(10000) rds := cache.NewRedis(redis.NewRing(&redis.RingOptions{ Addrs: map[string]string{ "server1": ":6379", }, })) cacheFactory := cache.NewFactory(rds, tinyLfu) // Create cache with local cache only, 10 minute TTL c := cacheFactory.NewCache([]cache.Setting{ { Prefix: "get-by-func", CacheAttributes: map[cache.Type]cache.Attribute{ cache.LocalCacheType: {TTL: 10 * time.Minute}, }, }, }) ctx := context.TODO() container := &Object{} // GetByFunc with inline getter - cache miss triggers getter execution err := c.GetByFunc(ctx, "get-by-func", "key2", container, func() (interface{}, error) { // This function is called only on cache miss // Typically read from database or microservice fmt.Println("Cache miss - fetching from database...") return Object{Str: "value2", Num: 2}, nil }) if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Retrieved: %+v\n", container) // Output: &{value2 2} // Second call hits cache, getter not executed container2 := &Object{} if err := c.GetByFunc(ctx, "get-by-func", "key2", container2, func() (interface{}, error) { fmt.Println("This won't be printed on cache hit") return Object{Str: "value2", Num: 2}, nil }); err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("From cache: %+v\n", container2) // Output: &{value2 2} } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.