英文:
Sharing Redis settings across routes
问题
我在我的routes.go
文件中有许多路由,它们都调用我的Redis数据库。我想知道如何避免在每个路由中调用dial
和AUTH
。
我尝试过在函数外部设置变量,像这样:
var (
c, err = redis.Dial("tcp", ADDRESS)
_, err = c.Do("AUTH", "testing")
)
但是编译器不允许两次使用err
。
英文:
I have a number of routes in my routes.go
file and they all call my redis database. I'm wondering how I can avoid calling the dial
and AUTH
calls in every route.
I've tried setting variables outside the functions like this:
var (
c, err = redis.Dial("tcp", ADDRESS)
_, err = c.Do("AUTH", "testing")
)
but then the compiler doesn't like err
being used twice.
答案1
得分: 4
首先,只使用var
来声明变量。你不能在函数外部运行代码,所以在var
语句中创建连接是没有意义的。如果你需要在启动时运行某些内容,可以使用init()
函数。
Redis连接不能用于并发请求。如果你想在多个路由之间共享一个Redis连接,你需要有一种安全的并发使用方法。在github.com/garyburd/redigo/redis
中,你可以使用Pool
。你可以在Dial函数中进行AUTH
调用,每次返回一个准备好的连接。
var redisPool *redis.Pool
func init() {
redisPool = &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", server)
if err != nil {
return nil, err
}
if _, err := c.Do("AUTH", password); err != nil {
c.Close()
return nil, err
}
return c, err
},
}
}
然后,每次需要连接时,你可以从连接池中获取一个连接,并在使用完毕后将其返回。
conn := redisPool.Get()
// conn.Close()只是将连接返回给连接池
defer conn.Close()
if err := conn.Err(); err != nil {
// conn.Err()将返回连接或Dial相关的错误
return nil, err
}
英文:
First, only use var for declaring variables. You can't run code outside of functions, so there's no use in trying to create connections inside a var statement. Use init()
if you need something run at startup.
The redis connections can't be used with concurrent requests. If you want to share a redis connection across multiple routes, you need to have a safe method for concurrent use. In the case of github.com/garyburd/redigo/redis
you want to use a Pool
. You can do the AUTH
call inside the Dial function, returning a ready connection each time.
var redisPool *redis.Pool
func init() {
redisPool = &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", server)
if err != nil {
return nil, err
}
if _, err := c.Do("AUTH", password); err != nil {
c.Close()
return nil, err
}
return c, err
},
}
}
Then each time you need a connection, you get one from the pool, and return it when you're done.
conn := redisPool.Get()
// conn.Close() just returns the connection to the pool
defer conn.Close()
if err := conn.Err(); err != nil {
// conn.Err() will have connection or Dial related errors
return nil, err
}
答案2
得分: 0
我会在main.go
中实例化一个连接池,并将引用传递给你的路由。这样一来,你只需要设置一次 Redis 客户端,然后你的路由就可以使用它。
我创建了一个围绕redigo
的装饰器,使得创建带有连接池的 Redis 客户端非常简单。而且它是类型安全的。
你可以在这里查看:https://github.com/shomali11/xredis
英文:
What I would do is instantiate a connection pool in main.go
and pass the reference to the pool to your routes. This way you are setting up your redis client once, and your routes can leverage it.
I created a decorator around redigo
that makes creating a Redis Client with a Connection pool very straightforward. Plus it is type-safe.
You can check it out here: https://github.com/shomali11/xredis
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论