Реализация кэширования или блокировки в golang?

# #go #caching #locking #access-token

Вопрос:

У меня есть случай использования, когда api нуждается в api_access_token…Я думаю о кэшировании токена и отслеживании времени истечения срока действия или блокировки на запрос для обработки параллельных запросов, любые предложения о том, как я могу реализовать или каким-либо идеальным способом?

 apiAccessToken = createAPIAccessToken(ctx, userId)
url := "https://<hostname>/<api>"

c := http.Client{Timeout: time.Duration(5) * time.Second}
myJson := bytes.NewBuffer([]byte(`{"key":"set.table.attr","Custom_Field":"yes"}`))

req, err := http.NewRequest("POST", url, myJson)
if err != nil {
    return
}
req.Header.Add("token", apiAccessToken)
res, err := c.Do(req)
defer res.Body.Close()
 

Комментарии:

1. вы можете оформить заказ github.com/patrickmn/go-cache если у вас есть небольшое количество значений, которые должны храниться локально в памяти, в противном случае необходимо искать внешнее кэширование, например redis

Ответ №1:

Может быть, что-то вроде этого поможет вам начать. Это возвращает все запросы из кэша и обновляет кэш в фоновом режиме асинхронно по расписанию time.Ticker

 package main

import(
    "fmt"
    "time"
    "sync"
)

type Cache struct {
    data interface{}
    update func(interface{})interface{}
    l sync.Mutex
    wg sync.WaitGroup
    update_period time.Duration
    done chan struct{}
}

func (c *Cache)Get() interface{} {
    c.l.Lock()
    defer c.l.Unlock()
    return c.data
}

func (c *Cache)periodicUpdater() {
        c.wg.Add(1)
        defer c.wg.Done()
        t := time.NewTicker(c.update_period)
        for {
            select{
                case <-t.C:
                    fmt.Println("Updating")
                    newdata := c.update(c.data)
                    c.l.Lock()
                    c.data = newdata
                    c.l.Unlock()
                case <-c.done:
                    t.Stop()
                    return
            }
        }
}


func main() {
    c := amp;Cache{
        update: func(data interface{}) interface{} {
            if d, ok := data.(int); !ok {
                panic("unexpected type")
            } else {
                return d 1
            }
        },
        update_period: 1 * time.Second,
        done: make(chan struct{}),
    }
    c.data = c.update(0)
    defer c.wg.Wait()
    go c.periodicUpdater()
    gt := time.NewTicker(773*time.Millisecond)
    for {
        select {
        case <-gt.C:
                x := c.Get()
                fmt.Println(x)
                if i, ok := x.(int); !ok {
                    panic("how was this not an int!?!")
                } else if i > 15 {
                    c.done <- struct{}{}
                    return
                }
        }
    }
}