如何在Go中建模这些类型

时间:2017-04-13 09:45:13

标签: go

我有多种类型:

// Using GridLayoutManager
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));

// Using StaggeredGridLayoutManager
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(numberOfColumns, StaggeredGridLayoutManager.VERTICAL));

它们都有两个共同的属性,type QueryMessage struct { Header MessageHeader Type MessageType Query SqlQuery } type UpdateMessage struct { Header MessageHeader Type MessageType OldData map[string]interface{} NewData map[string]interface{} } type InsertMessage struct { Header MessageHeader Type MessageType Data map[string]interface{} } Header。最后,我需要将它们聚合成一组通用消息。 目前我的Type界面如下所示:

Message

所以我基本上做的就是这样(将它们全部转换为Message接口):

type Message interface {}

这样做有效,但它丢失了所有类型信息,我希望仍然可以从q := QueryMessage{ ... } u := UpdateMessage{ ... } i := InsertMessage{ ... } allMessages := [3]Message { Message(q), Message(u), Message(i), } 类型中公开HeaderType(这样客户端代码理论上可以投射Message基于Message返回原始类型。

如何做到这一点?我无法找到正确的方法,界面不具备属性,如果我使Type成为结构,Go不允许我施放e。 G。一个MessageQueryMessage

2 个答案:

答案 0 :(得分:4)

您的界面可以提供访问者:

type Message interface {
   GetHeader() MessageHeader
   GetType() MessageType
}

然后,您必须在所有类型上实现此接口。

要分解公共部分,您可以使用额外的基本类型,并将其嵌入到其他结构中:

// the interface :
type Message interface {
    GetHeader() MessageHeader
    GetType() MessageType
}

// a base struct type, which holds 2 fields and implements the Message interface :
type baseMessage struct {
    Header MessageHeader
    Type   MessageType
}

func (b *baseMessage) GetHeader() MessageHeader {
    return b.Header
}

func (b *baseMessage) GetType() MessageType {
    return b.Type
}

// your three types, with an embedded "baseMessage" part :
type QueryMessage struct {
    baseMessage
    Query SqlQuery
}

type UpdateMessage struct {
    baseMessage
    OldData map[string]interface{}
    NewData map[string]interface{}
}

type InsertMessage struct {
    baseMessage
    Data map[string]interface{}
}

// compile time check : all the above types implement the Message interface :
var _ Message = &QueryMessage{}
var _ Message = &UpdateMessage{}
var _ Message = &InsertMessage{}

https://play.golang.org/p/Uho_2loXpZ

答案 1 :(得分:0)

只是一个意见,但考虑到HeaderType只是字段/数据而不是方法/行为,我丢失了消息interface而是使用消息struct

type Message struct {
    Header  MessageHeader
    Type    MessageType
    Details interface{}
}

然后根据Type字段的值,您可以将Details投射到任何内容。

if m.Type == QueryMessageType {
     q := m.Details.(SqlQuery)
} else if m.Type == UpdateMessageType {
     u := m.Details.(UpdateMessageDetails)
}

或者只使用类型开关

switch m.Details.(type) {
case SqlQuery:
     // ...
case UpdateMessageDetails:
     // ...
}