@@ -3,6 +3,7 @@ package cache
33import (
44 "context"
55 "fmt"
6+ "reflect"
67)
78
89type Item interface {
@@ -40,30 +41,24 @@ func (c *Typed[T]) SetOrFail(ctx context.Context, key string, value T, opts ...O
4041
4142func (c * Typed [T ]) Get (ctx context.Context , key string , opts ... GetOption ) (T , error ) {
4243 data , err := c .storage .Get (ctx , key , opts ... )
44+ var zero T
4345 if err != nil {
44- return * new ( T ) , fmt .Errorf ("failed to get value from cache: %w" , err )
46+ return zero , fmt .Errorf ("failed to get value from cache: %w" , err )
4547 }
4648
47- var value T
49+ value , err := newItem [T ]()
50+ if err != nil {
51+ return zero , err
52+ }
4853 if err := value .Unmarshal (data ); err != nil {
49- return * new ( T ) , fmt .Errorf ("failed to unmarshal value from cache: %w" , err )
54+ return zero , fmt .Errorf ("failed to unmarshal value from cache: %w" , err )
5055 }
5156
5257 return value , nil
5358}
5459
5560func (c * Typed [T ]) GetAndDelete (ctx context.Context , key string ) (T , error ) {
56- data , err := c .storage .GetAndDelete (ctx , key )
57- if err != nil {
58- return * new (T ), fmt .Errorf ("failed to get value from cache: %w" , err )
59- }
60-
61- var value T
62- if err := value .Unmarshal (data ); err != nil {
63- return * new (T ), fmt .Errorf ("failed to unmarshal value from cache: %w" , err )
64- }
65-
66- return value , nil
61+ return c .Get (ctx , key , AndDelete ())
6762}
6863
6964func (c * Typed [T ]) Delete (ctx context.Context , key string ) error {
@@ -81,9 +76,12 @@ func (c *Typed[T]) Drain(ctx context.Context) (map[string]T, error) {
8176 }
8277
8378 items := make (map [string ]T , len (data ))
84- for key , value := range data {
85- var item T
86- if err := item .Unmarshal (value ); err != nil {
79+ for key , raw := range data {
80+ item , err := newItem [T ]()
81+ if err != nil {
82+ return nil , err
83+ }
84+ if err := item .Unmarshal (raw ); err != nil {
8785 return nil , fmt .Errorf ("failed to unmarshal value from cache: %w" , err )
8886 }
8987
@@ -96,3 +94,20 @@ func (c *Typed[T]) Drain(ctx context.Context) (map[string]T, error) {
9694func (c * Typed [T ]) Close () error {
9795 return c .storage .Close ()
9896}
97+
98+ func newItem [T Item ]() (T , error ) {
99+ var zero T
100+
101+ t := reflect .TypeOf ((* T )(nil )).Elem ()
102+ if t .Kind () != reflect .Ptr {
103+ return zero , fmt .Errorf ("cache: type %s must be a pointer" , t .String ())
104+ }
105+
106+ v := reflect .New (t .Elem ())
107+ item , ok := v .Interface ().(T )
108+ if ! ok {
109+ return zero , fmt .Errorf ("cache: cannot create value of type %s" , t .String ())
110+ }
111+
112+ return item , nil
113+ }
0 commit comments