// 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 }