在Go中,给定一个接口{},我知道它实现了什么接口,如何转换成它
我目前的问题是,我正在实现数据结构,并且已经为它们编写了迭代器。我的数据结构、迭代器和所有其他必需的对象都有可见的接口。在后面,我有一些具体的实现,我希望对最终用户隐藏它们 这需要我的许多函数返回接口{}对象,以便我可以存储任何类型的对象(并将验证留给最终用户) 我遇到的一个问题是迭代一个图。我的图实现的迭代器{}返回一个具体的顶点类型,但迭代器接口返回接口{}。由于最终用户只能使用我的基本顶点界面,我必须尝试转换为顶点界面,以便他们可以使用它 这是我在这一点上能想到的最小的例子,它说明了我的问题:在Go中,给定一个接口{},我知道它实现了什么接口,如何转换成它,go,interface,Go,Interface,我目前的问题是,我正在实现数据结构,并且已经为它们编写了迭代器。我的数据结构、迭代器和所有其他必需的对象都有可见的接口。在后面,我有一些具体的实现,我希望对最终用户隐藏它们 这需要我的许多函数返回接口{}对象,以便我可以存储任何类型的对象(并将验证留给最终用户) 我遇到的一个问题是迭代一个图。我的图实现的迭代器{}返回一个具体的顶点类型,但迭代器接口返回接口{}。由于最终用户只能使用我的基本顶点界面,我必须尝试转换为顶点界面,以便他们可以使用它 这是我在这一点上能想到的最小的例子,它说明了我的问
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,而不是我希望的可爱值
编辑:删除了未使用的代码,我以为我已经删除了它,但我想没有。现在我已经完成了这篇长篇解释,我有了一个想法并想出了解决方案:
func convert(val interface{}) Base {
if con,ok := val.(Base); ok {
return con
}
return nil
}
不要试图强制转换到指针,而只是转换到基接口
我不知道为什么会这样。当我在convert中执行reflect.TypeOf(val)时,它会给出输出
*main.Concrete
我希望其他人觉得这很有用,并且其他人可以回答这个答案的为什么部分。现在我已经完成了这篇长篇解释,我有了一个想法并找到了解决方案:
func convert(val interface{}) Base {
if con,ok := val.(Base); ok {
return con
}
return nil
}
不要试图强制转换到指针,而只是转换到基接口
我不知道为什么会这样。当我在convert中执行reflect.TypeOf(val)时,它会给出输出
*main.Concrete
我希望其他人会觉得这很有用,也希望其他人能回答这个答案的为什么部分。你几乎不想使用指向接口的指针。例如,
*bytes.Buffer
(指向结构类型的指针)很常见,但*io.Reader
几乎总是一个错误。要真正理解为什么可能需要阅读以下内容:。@DaveC感谢您提供的链接,我们将查看它。让我感到困惑的一件事是,如果我想将指向某个结构的指针转换为接口,那么我不会将它作为指针保留。我的一个问题是指针部分发生了什么。如何将指针转换为非指针类型/接口?在该链接中已详细说明。接口值将指向任何底层类型,如果它是*具体的
,就这样吧。指向接口的指针不能实现该接口(例如func f(r io.Reader,rp*io.Reader)
可以调用r.Read
,但不能调用rp.Read
)。您几乎不想使用指向接口的指针。例如,*bytes.Buffer
(指向结构类型的指针)很常见,但*io.Reader
几乎总是一个错误。要真正理解为什么可能需要阅读以下内容:。@DaveC感谢您提供的链接,我们将查看它。让我感到困惑的一件事是,如果我想将指向某个结构的指针转换为接口,那么我不会将它作为指针保留。我的一个问题是指针部分发生了什么。如何将指针转换为非指针类型/接口?在该链接中已详细说明。接口值将指向任何底层类型,如果它是*具体的
,就这样吧。指向接口的指针没有实现该接口(例如,func f(r io.Reader,rp*io.Reader)
可以调用r.Read
,但不能调用rp.Read
)。如果你看一下,你会发现你的convert
函数只是base,
。它将根据需要返回零值(指针为nil)。但是,很少需要忽略布尔值。如果您的代码期望它是唯一添加元素的东西,那么使用base:=conc.(base)
是合适的。当运行时检测到代码中的错误时,您希望运行时死机,就像失败的片/数组边界检查会死机一样。@DaveC我之所以有一个方法,是因为我在几个地方调用了它。如果我改变了基础类型,我不想在很多地方改变它。我离开布尔检查的唯一原因是因为我喜欢它的外观。如果你看看,你会看到你的convert
函数就是base,:=conc.(base)
。它将根据需要返回零值(指针为nil)。但是,很少需要忽略布尔值。如果您的代码期望它是唯一添加元素的东西,那么使用base:=conc.(base)
是合适的。当运行时检测到代码中的错误时,您希望运行时死机,就像失败的片/数组边界检查会死机一样。@DaveC我之所以有一个方法,是因为我在几个地方调用了它。如果我改变了基础类型,我不想在很多地方改变它。我离开布尔检查的唯一原因是因为我喜欢它的外观。