blob: 30aebb2c948bea6174b5519c6e2f5fa61512f5d0 [file] [log] [blame]
// run
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
)
type AnyCacher[T any] interface {
// Get an item from the cache. Returns the item or nil, and a bool indicating
// whether the key was found.
Get(k string) (T, bool)
// Add an item to the cache, replacing any existing item.
Set(k string, x T)
}
// Item ...
type Item[T any] struct {
Object T
}
// AnyCache implements AnyCacher
type AnyCache[T any] struct {
*anyCache[T]
}
type anyCache[T any] struct {
items map[string]Item[T]
janitor *janitor[T] // Needed for the failure in the issue
}
// Set adds an item to the cache, replacing any existing item.
func (c *anyCache[T]) Set(k string, x T) {
c.items[k] = Item[T]{
Object: x,
}
}
// Get gets an item from the cache. Returns the item or nil, and a bool indicating
// whether the key was found.
func (c *anyCache[T]) Get(k string) (T, bool) {
// "Inlining" of get and Expired
item, found := c.items[k]
if !found {
var ret T
return ret, false
}
return item.Object, true
}
type janitor[T any] struct {
stop chan bool
}
func newAnyCache[T any](m map[string]Item[T]) *anyCache[T] {
c := &anyCache[T]{
items: m,
}
return c
}
// NewAny[T any](...) returns a new AnyCache[T].
func NewAny[T any]() *AnyCache[T] {
items := make(map[string]Item[T])
return &AnyCache[T]{newAnyCache(items)}
}
// NewAnyCacher[T any](...) returns an AnyCacher[T] interface.
func NewAnyCacher[T any]() AnyCacher[T] {
return NewAny[T]()
}
type MyStruct struct {
Name string
}
func main() {
// Create a generic cache.
// All items are cached as interface{} so they need to be cast back to their
// original type when retrieved.
// Failure in issue doesn't happen with 'any' replaced by 'interface{}'
c := NewAnyCacher[any]()
myStruct := &MyStruct{"MySuperStruct"}
c.Set("MySuperStruct", myStruct)
myRawCachedStruct, found := c.Get("MySuperStruct")
if found {
// Casting the retrieved object back to its original type
myCachedStruct := myRawCachedStruct.(*MyStruct)
fmt.Printf("%s", myCachedStruct.Name)
} else {
fmt.Printf("Error: MySuperStruct not found in cache")
}
// Output:
// MySuperStruct
}