【问题标题】:In Go, Given an interface{} in which I know what interface it implements, how can I convert to it在 Go 中,给定一个 interface{},我知道它实现了什么接口,我该如何转换它
【发布时间】:2015-08-31 03:38:21
【问题描述】:

我目前的问题是我正在实现数据结构并且我已经为它们编写了迭代器。我的数据结构、迭代器和所有其他必需对象都有可见的接口。在后面我有具体的实现,我希望对最终用户隐藏。

这需要我的许多函数返回 interface{} 对象,以便我可以存储任何类型的对象(并将验证留给最终用户)。

我遇到的一个问题是我迭代了一个图表。我的图实现的迭代器{}返回一个具体的顶点类型,但迭代器接口返回接口{}。由于最终用户只能使用我的基本 Vertex 接口,因此我必须尝试转换为 Vertex 接口以便他们可以使用它。

这是我此时能想到的最小示例,它说明了我的问题:

package main

import (
    "fmt"
    "strconv"
)

type Base interface {
    Required() string
}

type Concrete struct {
    _data int
}
func (con *Concrete) Required() string {
    return strconv.Itoa(con._data)
}

func convert(val interface{}) *Base {
    if con,ok := val.(*Base); ok {
        return con
    }
    return nil
}

func main() {
    conc := new(Concrete)
    conc._data = 5

    base := convert(conc)

    fmt.Println(base)
}

在上面的代码中,我真的希望 convert 将类型转换为 *Base。函数 convert 将返回值 nil 而不是我希望的可爱值。


编辑:删除了未使用的代码,我以为我已经删除了它,但我想没有。

【问题讨论】:

  • 如果您查看specification of type assertions,您会发现您的convert 函数只是base, _ := conc.(Base)。它将根据需要返回零值(指针为 nil)。但是,很少需要忽略布尔值。如果您的代码期望它是唯一添加元素的东西,那么使用base := conc.(Base) 是合适的。您希望运行时在检测到代码中的错误时发生恐慌,就像切片/数组边界检查失败一样会恐慌。
  • @DaveC 我有一个方法的原因是因为我在几个地方调用它。如果我更改基础类型,我不想在一堆地方更改它。我离开布尔检查的唯一原因是因为我喜欢它的外观。

标签: go interface


【解决方案1】:

写完这么长的解释后,我有了一个想法并想出了解决方案:

func convert(val interface{}) Base {
    if con,ok := val.(Base); ok {
        return con
    }
    return nil
}

不要尝试转换为指针,而只是转换为 Base 接口。

我不知道为什么会这样。当我在 convert 内部做 reflect.TypeOf(val) 时,它会给出输出

*main.Concrete

我希望其他人觉得这很有用,并且其他人可以回答这个答案的为什么部分。

【讨论】:

  • 您几乎从不想使用指向接口的指针。例如。 *bytes.Buffer(指向结构类型的指针)很常见,但 *io.Reader 几乎总是一个错误。要真正理解为什么可能需要阅读以下内容:Go Data Structures: Interfaces.
  • @DaveC 感谢您的链接将检查出来。让我感到震惊的一件事是,如果我想将指向某个结构的指针转换为接口,那么我不会将其保留为指针。我的一个问题是指针部分会发生什么。如何从指针转换为非指针类型/接口?
  • 在那个链接上都有解释。接口值将指向任何底层类型,如果是*Concrete,那就这样吧。指向接口的指针不实现该接口(例如,func f(r io.Reader, rp *io.Reader) 可以调用r.Read,但不能调用rp.Read)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-28
  • 2014-01-05
  • 1970-01-01
  • 2011-02-07
  • 2018-10-24
  • 1970-01-01
  • 2021-08-18
相关资源
最近更新 更多