一般來說,我們接收到消息,然后通過消息隊列發送消息給worker的時候,會有些額外的字段,這些字段不屬於實際的消息,我們想把實際的消息和發給worker的消息分開定義。這時候我們會把worker消息中一個字段定義為interface{}或者object,這個字段表示任意的實際消息。
type WorkerMsg struct { ID int Route string Msg interface{} // 實際消息 }
一切看起來很完美,但是問題來了,當我們用msgpack庫decode消息到worker消息結構體的時候,這個Msg字段變成了一堆object的集合體,這時候,我們不得不再寫一個函數把這些object,一個一個地復制到實際消息的結構體上,而這個函數是極其復雜的,很容易寫錯,而且性能也不好。
那么,我們還有更好的辦法嗎?其實我們可以這樣寫:
package main import ( "bytes" "fmt" "github.com/vmihailenco/msgpack" ) type Abc struct { BB int Haha int } type Msg struct { ID int Msg interface{} } func main() { var msg Msg msg.Msg = Abc{BB: 2, Haha: 3} var buf bytes.Buffer msgpack.NewEncoder(&buf).StructAsArray(true).Encode(msg) data := buf.Bytes() var workerMsg Msg realMsg := &Abc{} workerMsg.Msg = realMsg msgpack.Unmarshal(data, &workerMsg) fmt.Println(workerMsg, realMsg) }
可看到msgpack將數據解到msgD上,因為用的是指針,同時也解到了realMsg結構上! 這意味着我們不再需要重新定義一個新的結構體,而是組合這些結構體來實現我們的功能。