Golang Cast接口构造

时间:2018-06-20 02:50:36

标签: go redis

嗨,我正在尝试检索一个结构的功能/方法,但是我正在使用一个接口作为参数,并且正在使用该接口尝试访问该结构的功能。在下面演示我想要的是我的代码

// Here I'm trying to use "GetValue" a function of RedisConnection but since "c" is an interface it doesn't know that I'm trying to access the RedisConnection function. How Do I fix this?
func GetRedisValue(c Connection, key string) (string, error) {
    value, err := c.GetValue(key)

    return value, err
}

// Connection ...
type Connection interface {
    GetClient() (*redis.Client, error)
}

// RedisConnection ...
type RedisConnection struct {}

// NewRedisConnection ...
func NewRedisConnection() Connection {
    return RedisConnection{}
}

// GetClient ...
func (r RedisConnection) GetClient() (*redis.Client, error) {
    redisHost := "localhost"
    redisPort := "6379"

    if os.Getenv("REDIS_HOST") != "" {
        redisHost = os.Getenv("REDIS_HOST")
    }

    if os.Getenv("REDIS_PORT") != "" {
        redisPort = os.Getenv("REDIS_PORT")
    }

    client := redis.NewClient(&redis.Options{
        Addr:     redisHost + ":" + redisPort,
        Password: "", // no password set
        DB:       0,  // use default DB
    })

    return client, nil
}

// GetValue ...
func (r RedisConnection) GetValue(key string) (string, error) {
    client, e := r.GetClient()
    result, err := client.Ping().Result()
    return result, nil
}

2 个答案:

答案 0 :(得分:18)

要直接回答该问题,即将interface转换为具体类型,请执行以下操作:

v = i.(T)

其中i是接口,T是具体类型。如果基础类型不是T,它将感到恐慌。要进行安全类型转换,请使用:

v, ok = i.(T)

,并且如果基础类型不是T,则将ok设置为false,否则设置为ture。请注意,T也可以是接口类型,如果是,则代码会将i强制转换为新接口,而不是具体类型。

请注意,投射接口可能是不良设计的象征。就像在代码中一样,您应该问自己:自定义界面Connection仅需要GetClient还是总是需要GetValue?您的GetRedisValue函数需要一个Connection还是总是需要一个具体的结构?

相应地更改代码。

答案 1 :(得分:1)

您的Connection界面:

type Connection interface {
    GetClient() (*redis.Client, error)
}

只说有一个GetClient方法,没有说支持GetValue

如果您要像这样在GetValue上致电Connection

func GetRedisValue(c Connection, key string) (string, error) {
    value, err := c.GetValue(key)
    return value, err
}

然后您应该在界面中包含GetValue

type Connection interface {
    GetClient() (*redis.Client, error)
    GetValue(string) (string, error) // <-------------------
}

现在,您说的是所有Connection都将支持您要使用的GetValue方法。