我是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
。
我认为,如果我可以在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
}
然后在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还是很陌生。
谢谢!
答案 0 :(得分:4)
让我总结一下您的问题。
您有一个包含答复列表的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)
}
希望它会有所帮助:)。 有一个基于古尔冈的golang社区,随时准备帮助开发人员解决他们的问题。 您可以通过slack
加入社区答案 1 :(得分:1)
我知道,要返回不同的类型,返回参数必须是一个接口。因此,您可以像这样简单地声明函数:
func (a *Answer) DecodeData() (mode modeType, value interface{}) {}
模式表示该值为A记录或SRV记录,并且您可以使用 value 字段返回所需的任何内容。
函数调用者可以根据模式
处理值如果希望代码更优雅,可以为每种模式定义不同的值结构。然后,呼叫者可能会执行以下操作:
type modeType int
const (
ARecord modeType = 1
SRVRecord modeType = 2
)
switch mode {
case ARecord:
// do something
case SRVRecord:
// do something
}