以下代码中,getFunc 只支持一个参数,但我想支持多个参数。
(反射可以实现,但是不想用反射)
只基于 generic 还能进一步抽象支持多参数不?
package cache import ( "sync" "testing" ) type CacheFn[K comparable, V any] struct { redisMap sync.Map routineOnceMap sync.Map getFunc func(K) V } func NewCacheFn[K comparable, V any](getFunc func(K) V) *CacheFn[K, V] { return &CacheFn[K, V]{getFunc: getFunc} } // 1. 执行缓存到 redisMap 或其它存储; 2.如果多个协程同时执行时,只执行一次(其它协程被阻塞) func (c *CacheFn[K, V]) Get(key K) V { value, ok := c.redisMap.Load(key) if ok { return value.(V) } else { var once sync.Once onceInterface, loaded := c.routineOnceMap.LoadOrStore(key, &once) if loaded { // 如果有其它协程在执行,则等待它结束 oncePtr := onceInterface.(*sync.Once) oncePtr.Do(func() {}) } else { // 第一次访问,进行 DB 查询 once.Do(func() { value = c.getFunc(key) c.redisMap.Store(key, value) }) } val, _ := c.redisMap.Load(key) return val.(V) } } func TestCacheFuncWrapperGeneric(t *testing.T) { type UserInfo struct { Name string Age int } // 原始函数 getUserInfoFromDb := func(name string) UserInfo { println("get info from db:", name) return UserInfo{Name: name} } // 带缓存的函数 getUserInfoFromDbWithCache := NewCacheFn(getUserInfoFromDb) // getFunc 只接受一个参数,怎么接收多个参数呢? // 多个协程同时执行 batchCall := func(t *testing.T, fn func()) { var wg sync.WaitGroup for k := 0; k < 10; k++ { wg.Add(1) go func(i int) { fn() wg.Done() }(k) } wg.Wait() } // 多次调用函数, 只执行一次 batchCall(t, func() { userinfo := getUserInfoFromDbWithCache.Get("alex") t.Log(userinfo) }) }
![]() | 1 sora2blue 2023-07-29 00:58:21 +08:00 你可以把参数列表从`func(K) V`改成`func(...any) V`,参考`fmt.Printf`,不过这种办法需要自己取出参数做类型声明 如果你是想要直接传任意长度的带类型声明的参数列表,不如直接传一个结构体进去,结构体里面存参数,结构体的类型作为泛型声明的一部分 |
2 MAKF 2023-07-29 10:31:44 +08:00 ...argc, 当成 array 用 |
3 a132811 OP |
4 Anubisks 2023-07-31 07:09:07 +08:00 结构体吧 |