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结构上! 这意味着我们不再需要重新定义一个新的结构体,而是组合这些结构体来实现我们的功能。