1. 程式人生 > >【轉】msgpack庫的神奇用法

【轉】msgpack庫的神奇用法

一般來說,我們接收到訊息,然後通過訊息佇列傳送訊息給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結構上!  這意味著我們不再需要重新定義一個新的結構體,而是組合這些結構體來實現我們的功能。