在路由之间共享Redis设置

huangapple go评论97阅读模式
英文:

Sharing Redis settings across routes

问题

我在我的routes.go文件中有许多路由,它们都调用我的Redis数据库。我想知道如何避免在每个路由中调用dialAUTH

我尝试过在函数外部设置变量,像这样:

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

huangapple
  • 本文由 发表于 2015年5月15日 01:54:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/30244080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定