Source file test/typeparam/issue50109.go

     1  // run
     2  
     3  // Copyright 2021 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package main
     8  
     9  import (
    10  	"fmt"
    11  )
    12  
    13  type AnyCacher[T any] interface {
    14  	// Get an item from the cache. Returns the item or nil, and a bool indicating
    15  	// whether the key was found.
    16  	Get(k string) (T, bool)
    17  	// Add an item to the cache, replacing any existing item.
    18  	Set(k string, x T)
    19  }
    20  
    21  // Item ...
    22  type Item[T any] struct {
    23  	Object T
    24  }
    25  
    26  // AnyCache implements AnyCacher
    27  type AnyCache[T any] struct {
    28  	*anyCache[T]
    29  }
    30  
    31  type anyCache[T any] struct {
    32  	items   map[string]Item[T]
    33  	janitor *janitor[T] // Needed for the failure in the issue
    34  }
    35  
    36  // Set adds an item to the cache, replacing any existing item.
    37  func (c *anyCache[T]) Set(k string, x T) {
    38  	c.items[k] = Item[T]{
    39  		Object: x,
    40  	}
    41  }
    42  
    43  // Get gets an item from the cache. Returns the item or nil, and a bool indicating
    44  // whether the key was found.
    45  func (c *anyCache[T]) Get(k string) (T, bool) {
    46  	// "Inlining" of get and Expired
    47  	item, found := c.items[k]
    48  	if !found {
    49  		var ret T
    50  		return ret, false
    51  	}
    52  
    53  	return item.Object, true
    54  }
    55  
    56  type janitor[T any] struct {
    57  	stop chan bool
    58  }
    59  
    60  func newAnyCache[T any](m map[string]Item[T]) *anyCache[T] {
    61  	c := &anyCache[T]{
    62  		items: m,
    63  	}
    64  	return c
    65  }
    66  
    67  // NewAny[T any](...) returns a new AnyCache[T].
    68  func NewAny[T any]() *AnyCache[T] {
    69  	items := make(map[string]Item[T])
    70  	return &AnyCache[T]{newAnyCache(items)}
    71  }
    72  
    73  // NewAnyCacher[T any](...) returns an AnyCacher[T] interface.
    74  func NewAnyCacher[T any]() AnyCacher[T] {
    75  	return NewAny[T]()
    76  }
    77  
    78  type MyStruct struct {
    79  	Name string
    80  }
    81  
    82  func main() {
    83  	// Create a generic cache.
    84  	// All items are cached as interface{} so they need to be cast back to their
    85  	// original type when retrieved.
    86  	// Failure in issue doesn't happen with 'any' replaced by 'interface{}'
    87  	c := NewAnyCacher[any]()
    88  
    89  	myStruct := &MyStruct{"MySuperStruct"}
    90  
    91  	c.Set("MySuperStruct", myStruct)
    92  
    93  	myRawCachedStruct, found := c.Get("MySuperStruct")
    94  
    95  	if found {
    96  		// Casting the retrieved object back to its original type
    97  		myCachedStruct := myRawCachedStruct.(*MyStruct)
    98  		fmt.Printf("%s", myCachedStruct.Name)
    99  	} else {
   100  		fmt.Printf("Error: MySuperStruct not found in cache")
   101  	}
   102  
   103  	// Output:
   104  	// MySuperStruct
   105  }
   106  

View as plain text