Каналы с типом интерфейса и указатели на структуры как конкретные типы - PullRequest
0 голосов
/ 02 декабря 2018

Я пытаюсь обобщить часть своего кода, и я подумал, что смогу собрать вместе какой-то общий код, но я ударился головой о проблему системы типов.

Давайте предположим, что яу меня есть такой интерфейс:

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, но кажется, что это гораздо худший вариант.

Есть ли для этого чистое решение?

1 Ответ

0 голосов
/ 03 декабря 2018

Проблема в том, что 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

...