【问题标题】:Passing a collection of interface types to a function将接口类型的集合传递给函数
【发布时间】:2014-04-03 00:56:25
【问题描述】:

我无法找出在 Go 中使用接口的正确方法。我的函数需要获取实现某种方法的项目的映射。它看起来像这样:

type foo interface {
    bar() string
}

func doSomething(items map[string]foo) {

}

我正在尝试使用实现foo 接口的类型调用此函数。

type baz struct { }

func (b baz) bar() string {
    return "hello"
}

items := map[string]baz{"a": baz{}}
doSomething(items)

但我收到以下错误:

cannot use items (type map[string]baz) as type map[string]foo in function argument

但是,当我这样做时它工作正常:

items := map[string]foo{"a": baz{}}
doSomething(items)

但我想针对不同的界面重复使用同一张地图。基本上我索引了很多对象,然后将它们传递给需要实现不同接口来计算结果的各种函数。我想将地图作为foo 的地图传递给一个函数,并将另一个函数作为foobar 的地图传递。

我尝试了各种类型断言和转换,但似乎没有任何效果,所以我不确定我只是没有使用正确的语法还是完全错误。

去游乐场http://play.golang.org/p/8mMWCDG7vm

【问题讨论】:

    标签: interface go


    【解决方案1】:

    这是一个相当常见的错误。

    您正在混合这两种不同的类型:

    map[string]foo
    
    map[string]baz
    

    您不能简单地将一种地图类型转换为另一种地图类型。 converting []T slices to []interface{} slicesconverting chan T to chan interface{} 也是如此(相同的问题/答案,但针对频道)。

    map[string]foo 表示 foo 接口的映射,并非所有类型 map[string]T 其中 T 实现了 foo 接口。

    您可以通过进行此更改来解决它:

    items := map[string]foo{"a": baz{}}
    

    游乐场: http://play.golang.org/p/HxIVGSptwk

    编辑:

    拥有接口映射允许您将不同的接口值类型转换为其他类型的接口。所以地图可以重复使用。

    游乐场: http://play.golang.org/p/20YMWmDjYT

    但是你应该有一个接口类型的映射,它是由要存储在映射中的类型实现的所有不同方法的交集。如果没有交集,则必须使用interface{} 以确保可以存储任何类型。

    【讨论】:

    • 我知道map[string]foo 有效(请参阅我的原始问题),但我希望我错过了一些东西。处理需要使用接口传递的结构集合的 Go 惯用方法是什么?您是否为每种接口类型重新创建整个地图?以某种方式为地图类型创建接口?
    • 如果您要传递它,我建议仍将其保留为接口图。如果这样做,您可以在需要时将值转换为 foobar:请参阅编辑示例。
    • 啊,我明白了。想要接口 foobar 似乎真的很奇怪,但接受接口 foo 只是为了以后可以将其转换为所需的接口。意味着即使所需的接口类型是静态的,也不进行编译时类型检查。
    • 是的,在那种情况下很奇怪。我刚刚添加到编辑中,您可能希望对映射值使用不同的接口,以确保应该存储在映射中的任何类型实际上都实现了该接口。就像,如果您要存储 io.Writer 和有时 io.ReadWriter 的,您想使用 io.Writer 的接口,因为它是由您将存储的所有类型实现的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    相关资源
    最近更新 更多