为了账号安全,请及时绑定邮箱和手机立即绑定

Golang接口的正确使用

Golang接口的正确使用

Go
呼啦一阵风 2023-05-22 15:15:46
我是 Go 的新手,遇到了不确定如何解决的情况。我正在编写一些代码,这些代码以原始字节形式获取 DNS 数据包并返回一个名为 DNSPacket 的结构。该结构如下所示type DNSPacket struct {    ...some fields    Questions  []Question    Answers    []Answer    ...some more fields}我遇到的问题是 Answers 类型,看起来像这样。 type Answer struct {    Name     string    Type     int    Class    int    TTL      uint32    RdLength int    Data     []byte}根据 Answer 的类型,Data必须对字段进行不同的解码。例如,如果答案是一条A记录(类型 1),则数据只是一个 ipv4 地址。但是,如果 Answer 是SRV记录(类型 33),则数据包含port, priority,weight并target在字节切片中编码。我认为如果我可以在 Answer 上调用一个方法,根据类型返回正确的数据,那会很棒,DecodeData()但是由于 Go 中没有覆盖或继承,我不确定如何解决这个问题。我尝试使用接口来解决这个问题,但它无法编译。我试过类似的东西type DNSRecordType interface {    Decode(data []byte)}type RecordTypeSRV struct {   target string   ...more fields}//to 'implement' the DNSRecordType interfacefunc (record *RecordTypeSRV) Decode(data []byte) {    //do the work to decode appropriately and set    //the fields on the record}然后在 Answer 方法中func (a *Answer) DecodeData() DNSRecordType {    if a.Type === SRVType {       record := RecordTypeSRV{}       record.Decode(a.Data)       return record    }    //do something similar for other record types }具有单一 Answer 类型但能够根据其类型返回不同类型的 Answer Data 的正确 Go 方法是什么?抱歉,如果这是一个完全初学者的问题,因为我对 Go 还是很陌生。
查看完整描述

2 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

让我总结一下你的问题。


您有一个包含答案列表的 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

}

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


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)

}


查看完整回答
反对 回复 2023-05-22
?
POPMUISE

TA贡献1765条经验 获得超5个赞

据我所知,要返回不同的类型,返回参数必须是一个接口。所以你可以像这样简单地声明函数:


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

mode表示值为 A 记录或 SRV 记录,您可以使用value字段返回任何您想要的内容。


函数调用者可以根据模式处理值


如果你想让代码更优雅,你可以为每个模式定义不同的值结构。然后调用者可以如下操作:


type modeType int


const (

    ARecord modeType = 1

    SRVRecord modeType = 2

)


switch mode {

    case ARecord:

    // do something

    case SRVRecord:

    // do something


查看完整回答
反对 回复 2023-05-22
  • 2 回答
  • 0 关注
  • 86 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信