【问题标题】:Golang Cast interface to structGolang Cast接口到结构
【发布时间】:2018-06-20 02:50:36
【问题描述】:

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

// 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
}

【问题讨论】:

  • GetValue 返回一个接口。使用 redis.String() 将其转换为字符串

标签: go redis


【解决方案1】:

要直接回答问题,即将interface 转换为具体类型,您可以:

v = i.(T)

其中i 是接口,T 是具体类型。如果底层类型不是 T,它会恐慌。为了有一个安全的转换,你使用:

v, ok = i.(T)

如果底层类型不是T,则ok设置为false,否则设置为true。请注意,T 也可以是接口类型,如果是,代码将 i 转换为新接口而不是具体类型。

请注意,铸造界面可能是糟糕设计的象征。在您的代码中,您应该问自己,您的自定义界面Connection 是否只需要GetClient 还是总是需要GetValue?你的GetRedisValue 函数需要Connection 还是它总是需要一个具体的结构?

相应地更改您的代码。

【讨论】:

  • 我很高兴发现这种类型的转换在 golang 中是可能的,当我读到你的最后一段时,我正要开始使用它......然后 :( 回到设计图并避免使用这种类型的投射。您的笔记绝对正确,谢谢!
【解决方案2】:

你的Connection界面:

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

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

如果你想像这样在Connection 上调用GetValue

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) // <-------------------
}

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

【讨论】:

  • 是的,我认为会是这样。但是 Connection 接口将具有 GetValue 方法是没有意义的。所以我想有一个单独的接口,里面有一个 GetValue 函数。我将如何处理?
  • 这取决于你想去兔子洞多远。你真的需要你的Connection 接口吗?也许您只需要某种 type Valuer interface { GetValue(string) (string, error) } 然后只需将您的 redis 连接包装在实现该接口的结构中。
猜你喜欢
  • 2016-10-15
  • 2023-03-04
  • 2020-03-31
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
相关资源
最近更新 更多