为什么这两个Go代码的行为不同?

时间:2018-10-17 08:00:24

标签: go closures

我有2台Redis服务器(数据分散到2台服务器),并且应该针对给定的密钥对这两个服务器运行GET操作。

我的代码的第一个版本:

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

var pools []*redis.Pool

func main() {
    readServers := []string{
        "my-redis-server1:6379",
        "my-redis-server2:6379",
    }

    for _, s := range readServers {
        pools = append(pools, &redis.Pool{
            MaxIdle: 5,
            Dial: func() (redis.Conn, error) {
                fmt.Printf("server: %s\n", s)
                c, err := redis.Dial("tcp", s)
                if err != nil {
                    panic(err.Error())
                }
                return c, err
            },
        })
    }

    for i, p := range pools {
        c := p.Get()
        defer c.Close()

        res, err := redis.String(c.Do("GET", "key"))
        fmt.Printf("pools[%d] res: %s, err: %s\n", i, res, err)
    }
}

my-redis-server2具有键key的数据(值:value),因此预期输出为:

server: my-redis-server1:6379
pools[0] res: , err: redigo: nil returned
server: my-redis-server2:6379
pools[1] res: value, err: %!s(<nil>)

但是实际输出是:

server: my-redis-server2:6379
pools[0] res: value, err: %!s(<nil>)
server: my-redis-server2:6379
pools[1] res: value, err: %!s(<nil>)

我想知道为什么实际输出为池[0]输出my-redis-server2:6379而不是my-redis-server1:6379

下面的代码是第二个版本,它可以按预期运行:

package main

import (
    "fmt"

    "github.com/garyburd/redigo/redis"
)

var pools []*redis.Pool

func newPool(svr string) *redis.Pool {
    return &redis.Pool{
        MaxIdle: 5,
        Dial: func() (redis.Conn, error) {
            fmt.Printf("server: %s\n", svr)
            c, err := redis.Dial("tcp", svr)
            if err != nil {
                panic(err.Error())
            }
            return c, err
        },
    }
}

func main() {
    readServers := []string{
        "my-redis-server1:6379",
        "my-redis-server2:6379",
    }

    for _, s := range readServers {
        pools = append(pools, newPool(s))
    }

    for i, p := range pools {
        c := p.Get()
        defer c.Close()

        res, err := redis.String(c.Do("GET", "key"))
        fmt.Printf("pools[%d] res: %s, err: %s\n", i, res, err)
    }
}

第一和第二代码之间的主要区别是什么?我不明白提取函数如何影响结果。

0 个答案:

没有答案