#go #redis
#Вперед #redis
Вопрос:
Я использую redis для хранения сеансов для моего простого веб-приложения Go. Для этого мне нужен только один сеанс для одновременного доступа к соединению redis. Я искал информацию о реализации одноэлементных объектов в Go и следовал. Это код, который я сейчас внедряю:
Подключение Redis:
package Datab
import (
"github.com/gomodule/redigo/redis"
)
type cache struct {
Conn redis.Conn
}
var singleCache *cache = nil
func GetSessionCache() *cache {
if singleCache == nil {
singleCache := amp;cache{}
singleCache.Conn, _ = redis.DialURL("redis://localhost")
// ^ SINGLECACHE IS NOT NIL HERE.
}
return singleCache
// ^ SAYS THIS IS NIL!
}
Реализация Redis:
package Handler
import (
Datab "videodoox/DB" // this file contains the redis connection implementation
)
connStru := *Datab.GetSessionCache()
cache := connStru.Conn
connStru2 := *Datab.GetSessionCache()
cache2: = connStru.Conn
// ^ THIS CONNECTION HERE IS A COMPLETELY NEW INSTANCE.
Каждый раз, когда я получаю соединение, файл подключения redis создает новый экземпляр соединения.
Как мне создать новое соединение один раз и просто возвращать это соединение каждый раз?
Спасибо!
Комментарии:
1.
singleCache := amp;cache{}
=> Это короткое объявление переменной, которое создает новую локальную переменную, затеняющую глобальную. Используйте назначение:singleCache = amp;cache{}
. Также это небезопасно для одновременного использования. Лучше всего было бы выполнить инициализациюsingleCache
в функции packageinit()
(или использоватьonce.Do()
, если вам нужна отложенная инициализация).2. @icza О, черт, я такой тупой! Это сработало как по волшебству! Большое спасибо. Да, я планирую использовать mutex для блокировки моих потоков и обеспечения потокобезопасности.
3. Обратите внимание на документацию Redigo по параллелизму . Вам нужно будет использовать мьютекс для управления доступом к методам подключения или изменить
cache
поле на пул.4. попробуйте использовать это marcio.io/2015/07/singleton-pattern-in-go
Ответ №1:
Комментарии к первоначальному вопросу решают проблему, но просто для обеспечения полного решения ваш код может выглядеть следующим образом:
package Datab
import (
"sync"
"github.com/gomodule/redigo/redis"
)
type cache struct {
Conn redis.Conn
}
var singleCache *cache
var initOnce sync.Once
func GetSessionCache() *cache {
initOnce.Do(func() {
singleCache := amp;cache{}
singleCache.Conn, _ = redis.DialURL("redis://localhost")
})
return singleCache
}
Всего пара дополнительных замечаний:
- Нет необходимости указывать
nil
в качестве начального значения указателей нулевое значение для нихnil
по умолчанию (var singleCache *cache
vsvar singleCache *cache = nil
). - Вы должны обработать потенциальную ошибку, возвращаемую
redis.DialURL
, а не просто пропустить ее с помощью_
.