Golang 接口的正确使用

Ale*_*nca 2 dns go

我是 Go 的新手,遇到了我不确定如何解决的情况。我正在处理一些以原始字节形式接收 DNS 数据包并返回一个名为 DNSPacket 的结构的代码。

结构如下所示

type DNSPacket struct {
    ...some fields
    Questions  []Question
    Answers    []Answer
    ...some more fields
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是答案类型,看起来像这样。

 type Answer struct {
    Name     string
    Type     int
    Class    int
    TTL      uint32
    RdLength int
    Data     []byte
}
Run Code Online (Sandbox Code Playgroud)

根据 Answer 的类型,Data必须对字段进行不同的解码。例如,如果答案是A记录(类型 1),则数据只是一个 ipv4 地址。然而,如果应答是一个SRV记录(33型),那么数据被包含portpriorityweighttarget在字节切片进行编码。

我认为如果我可以在 Answer 上调用一个方法来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
}
Run Code Online (Sandbox Code Playgroud)

然后在答案方法中

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

    //do something similar for other record types
 }
Run Code Online (Sandbox Code Playgroud)

拥有单一答案类型但能够根据其类型返回不同类型的答案数据的正确 Go 方式是什么?抱歉,如果这是一个完全初学者的问题,因为我对 Go 还是很陌生。

谢谢!

小智 5

让我总结一下你的问题。

您有一个带有答案列表的 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
}
Run Code Online (Sandbox Code Playgroud)

回答 让我们创建一个应该被实现来处理数据的接口。

type PacketProcessor interface {
    Process(Answer)
}
Run Code Online (Sandbox Code Playgroud)

让 SRV 实现 PacketProcessor

type SRV struct {
    ...
}

func (s *SRV) Process(a Answer) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

你的处理逻辑应该如下

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

    //finally
    p.Process(*a)
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你 :)。有一个基于 Gurgaon 的 golang 社区,随时准备帮助开发人员解决他们的问题。您可以通过slack加入社区