1. 程式人生 > >go實現一個簡單的遊戲伺服器框架(lotou)編碼

go實現一個簡單的遊戲伺服器框架(lotou)編碼

程式碼倉庫

在lotou中實現了兩種二進位制編碼方式。

binary

一種是普通的C/C++模式的小端編碼方式,每一個數據都被依次編碼進一個二進位制流中,基本用法如下:

  • 編碼
    binary.Encode(v)
    binary.Encode(v)
  • 解碼
    binary.Decode(&v)
    binary.Decode(&v)

使用非常簡單,編碼方式也很簡單。

還有一種是為了用於lotou內部通訊(後面即將實現的多節點實現中會用到)

gob

在這種方式中,編碼的時候會將資料的型別也編碼進二進位制流中,這樣可以讓解碼端直接根據二進位制流中的型別生成對應的資料,而不是需要根據傳入的引數來判斷資料需要如何解析。
之所以需要這樣做,是因為在服務和服務之間傳送資料的時候,傳送的實際上是一個[]interface{}的型別,slice的元素的實際型別是未知的,所以必須使編碼是型別自描述的。目前該編碼方式可以支援除複數外的所有的內建資料型別,以及提前註冊進編碼中的結構體(所有註冊的結構體必須在每一個節點都以相同的順序註冊,因為現在的型別是使用的ID表示,如果註冊順序不一致,會導致解析型別不匹配)。
使用方法也很簡單

  • 編碼
    gob.Encode(v1)
    gob.Encode(v2)
  • 解碼
    v, e := gob.Decode()
    v, e := gob.Decode()

要注意decode返回的是一個interface,實際型別在分發到對應服務的時候,由dispatchM函式通過reflect.Value的Call方法自動進行轉換。

reflect.Value.Call
func (v Value) Call(in []Value) []Value
這函式中v是一個函式的reflect.Value,in是函式的引數,並且函式的返回值也放在一個Value的slice裡面返回。in的每一個元素對應v的一個引數,並且他們必須一一是可賦值的。即in[i]的實際型別是必須是可以賦值給函式的第i個引數的
如果函式的輸入有可變引數,那麼Call會自動生成可變引數的slice。如果v不是一個func,那麼Call函式會panic。