Итак, я новичок в каналах, группах ожидания, мьютексе и т. Д. 1011 *, и попытался создать приложение, которое запрашивает фрагмент структуры для данных и, если оно находит данные, загружает его в карту. Я в основном пытаюсь реплицировать сценарий cache / db (но в настоящее время оба находятся в памяти для простоты понимания).
Теперь, при запросе данных, он запрашивается как из базы данных, так и из кеша, и я ' для этого мы установили RWMutex; но при чтении данных, сохраненных либо в кэш, либо в базу данных, используя другие подпрограммы go (по каналам). Он читает как из (db go -программы), так и из (cache go -программы). Так что я делал каждый раз, когда получал чтение из кеша go -программа я тратил db go -рассмотрение одного элемента.
package main
import (
"fmt"
"math/rand"
"strconv"
"sync"
"time"
)
type Book struct {
id int
name string
}
var cache = map[int]Book{}
var books []Book
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
func main() {
cacheCh := make(chan Book)
dbCh := make(chan Book)
wg := &sync.WaitGroup{}
m := &sync.RWMutex{}
loadDb()
for i := 0; i < 10; i++ {
id := rnd.Intn(10)
wg.Add(1)
go func(id int, wg *sync.WaitGroup, m *sync.RWMutex, ch chan<- Book) {
if find, book := queryCache(id, m); find {
fmt.Println("Found Book In Cache: ", book)
ch <- book
}
wg.Done()
}(id, wg, m, cacheCh)
wg.Add(1)
go func(id int, wg *sync.WaitGroup, m *sync.RWMutex, ch chan<- Book) {
if find, book := queryDb(id, m); find {
ch <- book
}
wg.Done()
}(id, wg, m, dbCh)
go func(dbCh, cacheCh <-chan Book) {
var book Book
select {
case book = <-cacheCh:
msg := <-dbCh
fmt.Println("Drain DbCh From: ", msg, "\nBook From Cache: ", book.name)
case book = <-dbCh:
fmt.Println("Book From Database: ", book.name)
}
}(dbCh, cacheCh)
}
wg.Wait()
}
func queryCache(id int, m *sync.RWMutex) (bool, Book) {
m.RLock()
b, ok := cache[id]
m.RUnlock()
return ok, b
}
func queryDb(id int, m *sync.RWMutex) (bool, Book) {
for _, val := range books {
if val.id == id {
m.Lock()
cache[id] = val
m.Unlock()
return true, val
}
}
var bnf Book
return false, bnf
}
func loadDb() {
var book Book
for i := 0; i < 10; i++ {
book.id = i
book.name = "a" + strconv.Itoa(i)
books = append(books, book)
}
}
Кроме того, я понимаю, что в этом коде он всегда будет запрашивать БД, даже если он находит попадание в кеш, что не идеально. Но это всего лишь тестовый сценарий, в котором все, что я поставил в качестве приоритета, заключается в том, что пользователь получает сведения в самом быстром из возможных режимов (ie, если он отсутствует в кэше, он не должен ждать ответа от кеш, прежде чем запрашивать базу данных).
Пожалуйста, помогите, если возможно, я довольно новичок в этом, так что это может быть что-то тривиальное.
Извините и спасибо.