Голанг правильное использование интерфейсов - PullRequest
0 голосов
/ 20 декабря 2018

Я новичок в Go и столкнулся с ситуацией, которую я не знаю, как решить.Я работаю над кодом, который принимает пакет DNS в необработанных байтах и ​​возвращает структуру с именем DNSPacket.

Структура выглядит следующим образом:

type DNSPacket struct {
    ...some fields
    Questions  []Question
    Answers    []Answer
    ...some more fields
}

Проблема, с которой я столкнулся, связана сТип ответа, который выглядит следующим образом.

 type Answer struct {
    Name     string
    Type     int
    Class    int
    TTL      uint32
    RdLength int
    Data     []byte
}

В зависимости от типа ответа поле Data должно быть декодировано по-разному.Например, если Ответом является запись A (Тип 1), данные являются просто адресом ipv4.Однако, если Ответ является записью SRV (Тип 33), тогда данные содержат port, priority, weight и target, закодированные в байтовом срезе.

Я подумал, что было бы здорово, если бы у меня был метод ответа с именем DecodeData(), который возвращает правильные данные в зависимости от типа, однако, поскольку в Go нет переопределения или наследования, я не уверен, как решитьэтот.Я попытался использовать интерфейс для решения этой проблемы, но он не скомпилируется.Я попробовал что-то вроде

type DNSRecordType interface {
    Decode(data []byte)
}


type RecordTypeSRV struct {
   target string
   ...more fields
}
//to 'implement' the DNSRecordType interface
func (record *RecordTypeSRV) Decode(data []byte) {
    //do the work to decode appropriately and set
    //the fields on the record
}

Затем в методе ответа

func (a *Answer) DecodeData() DNSRecordType {
    if a.Type === SRVType {
       record := RecordTypeSRV{}
       record.Decode(a.Data)
       return record
    }

    //do something similar for other record types
 }

Каков будет правильный способ использования Go с одним типом ответа, но с возможностью возвращать разные типы ответаДанные в зависимости от их типа?Извините, если это вопрос для начинающих, так как я все еще новичок в Go.

Спасибо!

Ответы [ 2 ]

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

Как я знаю, чтобы возвращать разные типы, возвращаемый параметр должен быть интерфейсом.Таким образом, вы можете просто объявить функцию следующим образом:

func (a *Answer) DecodeData() (mode modeType, value interface{}) {}

mode означает, что значением является запись A или запись SRV, и вы можете вернуть все, что захотите, со значением field.

Вызывающий функцию может обрабатывать значение в зависимости от режима

Если вы хотите, чтобы код был более элегантным, вы можете определитьразличные значения структуры для каждого режима.Тогда вызывающий абонент может действовать следующим образом:

type modeType int

const (
    ARecord modeType = 1
    SRVRecord modeType = 2
)

switch mode {
    case ARecord:
    // do something
    case SRVRecord:
    // do something
} 
0 голосов
/ 20 декабря 2018

Позвольте мне обобщить ваш вопрос.

У вас есть пакет DNS со списком ответов.В зависимости от типа ответа вы должны обработать данные в ответе.

type DNSPacket struct {
    ...some fields
    Questions  []Question
    Answers    []Answer
    ...some more fields
}
type Answer struct {
    Name     string
    Type     int
    Class    int
    TTL      uint32
    RdLength int
    Data     []byte
}

Ответ Давайте создадим интерфейс, который должен быть реализован для обработки данных.

type PacketProcessor interface {
    Process(Answer)
}

Пусть SRV реализует PacketProcessor

type SRV struct {
    ...
}

func (s *SRV) Process(a Answer) {
    ...
}

Ваша логика обработки должна выглядеть следующим образом

func (a *Answer) Process() {
    var p PacketProcessor
    switch a.Type {
        case SRVType:
        p = &SRV{}
        ...
        //other cases
    }

    //finally
    p.Process(*a)
}

Надеюсь, это поможет :).Существует сообщество голангов в Гургаоне, которое всегда готово помочь разработчикам с их проблемами.Вы можете присоединиться к сообществу через slack

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...