【问题标题】:Channels with interface type and pointers to structs as concrete types具有接口类型的通道和指向结构的指针作为具体类型
【发布时间】:2019-05-04 02:40:31
【问题描述】:

我正在尝试概括我的一些代码,并且我认为我可以将一些通用代码组合在一起,但我遇到了类型系统问题。

假设我有一个这样的界面:

type Hashable interface {
    GetHash() []byte
}

我有几个像这样的具体类型:

type Transaction struct {
    Hash                 []byte    `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
}

func (m *Transaction) GetHash() []byte {
    if m != nil {
        return m.Hash
    }
    return nil
}

请注意,这些是由protoc 生成的,我可能无法轻易更改它们。虽然类型本身没有实现Hashable,但如果我没记错的话,应该是指向结构的指针。

当我创建一个接受chan Hashable 类型的通道并尝试传入chan *Transaction 的函数时出现问题,如下所示:

func consume(c chan Hashable) {
    // Do something with the elements from c
}

func main() {
    var c2 chan *Transaction
    consume(c2)
}

(我在Playground 中创建了一个小例子来展示这个问题)

我当然可以创建一个新结构来重新打包consume 需要的字段,但这似乎是一个更糟糕的选择。

有没有干净的解决方案?

【问题讨论】:

  • 有什么理由不能将c2 创建为chan *Hashable
  • @MTCoster OP 可能会想要 chan Hashable。您不需要经常使用指向接口的指针。
  • 好问题,我还计划在另一个上下文中重用chan *Transaction,我实际上需要将元素设置为*Transaction。我可以创建一个函数,通过读取一个通道并写入另一个通道来进行转换,但这似乎有点浪费(上下文切换、额外的 gorouting 等)。
  • 如果你听从 Gavin 的建议并放下指针,你可以使用其中一个,在另一种情况下使用。
  • 请注意,chan Hashable 没有指针,而这正是我试图开始工作的情况:-)

标签: go interface channel


【解决方案1】:

问题是:chan *Transaction 不是一个接口——它是一个特定的类型。所以它本质上不能实现接口或chan Hashable。您需要使用特定的频道。

您可以使用这样的灌浆即时将Transaction 值转换为Hashable

func convertor(ct chan *Transaction) chan Hashable {
    ch := make(chan Hashable)
    go func() {
        for t := range(ct) {
            ch <- Hashable(t)
        }

    }()
    return ch
}

并调用

consume(convertor(c2))

https://play.golang.org/p/pd2EfhCehYz

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 2011-06-09
    相关资源
    最近更新 更多