2017-04-13 28 views
1

這些類型的模式,我有多種類型這樣的:如何去

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{} 
} 

他們都有一個共同點,HeaderType兩個屬性。最後,我需要將它們聚合成一個通用消息數組。 目前我Message界面看起來是這樣的:

type Message interface {} 

所以我基本上做的是這樣的(他們所有鑄造到Message接口):

q := QueryMessage{ ... } 
u := UpdateMessage{ ... } 
i := InsertMessage{ ... } 
allMessages := [3]Message { Message(q), Message(u), Message(i), } 

這工作,但它失去所有類型信息,我希望仍然能夠從Message類型中暴露HeaderType(這樣客戶端代碼在理論上可以將基於TypeMessage轉換回它的原始類型

這怎麼辦?我找不到一個合適的方法,接口不能有屬性,如果我使Message成爲一個結構體,Go不允許我使用e。 G。一個QueryMessageMessage了。

+1

僅供參考,你並不需要,如果該值的類型實現該接口的值轉換爲一個接口。即'[3] Message {q,u,i}'會編譯得很好。 – mkopriva

回答

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

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: 
    // ... 
}