想請教一下,我現在在學習使用golang websocket跟protobuf使用架設server,目前遇到問題就是protobuf直接限定了發送跟接收的struct結構,可是應該我要使用websocket接收而不是用grpc所以導致了我不能每次都用特定的格式去接收[]byte,想問一下有什麼方法可以不特定結構的反序列化接收的data呢?
我所有設定的struct的request裡面都有一個變數叫做messageCode,想利用這個來分辨,以下是我的proto檔
//補充
抱歉,可能是我表達得還不夠清楚,我已經寫到接收的部分了,以上面給的proto檔來說,目前接收的request就兩種,Ping跟GetDataRequest
問題是在proto.Unmarshal這裡,如果我request傳的是Ping,那我Unmarshal的結構就一定要用Ping來接才能反序列化成功,可是問題是我有可能傳Ping也有可能傳GetDataRequest,如果在傳GetDataRequest的話反序列化就會失敗,我找了很久都沒有找到一個通用的結構兩個都可以反序列化成功,又沒有辦法只提取出messageCode來確認是什麼。
看了一下感覺可以啊
我的理解是你想用protobuf當IDL
然後用websocket當通訊協定溝通
所以
data, err := proto.Marshal(s)
if err != nil {
log.Fatal(err)
}
c, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:8899/echo", nil)
if err != nil {
log.Fatal("dial:", err)
}
defer c.Close()
err = c.WriteMessage(websocket.TextMessage, data)
if err != nil {
log.Println(err)
return
}
https://jiepeng.me/2018/07/25/protocol-buffers-intro
https://ithelp.ithome.com.tw/articles/10208531
抱歉,可能是我表達得還不夠清楚,我已經寫到接收的部分了,以上面給的proto檔來說,目前接收的request就兩種,Ping跟GetDataRequest
問題是在proto.Unmarshal這裡,如果我request傳的是Ping,那我Unmarshal的結構就一定要用Ping來接才能反序列化成功,可是問題是我有可能傳Ping也有可能傳GetDataRequest,如果在傳GetDataRequest的話反序列化就會失敗,我找了很久都沒有找到一個通用的結構兩個都可以反序列化成功,又沒有辦法只提取出messageCode來確認是什麼。
看能不能用泛型(go >= 1.18)解決,不能你就用個interface{}去接,然後接到函數內做類型判斷。
https://alankrantas.medium.com/%E7%B0%A1%E5%96%AE%E7%8E%A9-go-1-18-%E6%B3%9B%E5%9E%8B-1d09da07b70
兩個我都試過了,都沒辦法的樣子,一直卡在所謂的protouface.MessageV1
你interface{}接收完要自己去做類型斷言/反射,去判斷類型啊,直接丟到Unmarshal當然會出錯。
泛型我是不知道Unmarshal有沒有支援,有的話你前面也得加類型,反正你都離不開類型判斷。
另外實務上這種不同參數類型要共用一條路由的狀況很少,了不起就是optional value的差別,通常會開另外一條路由去專一處理,因為這違反SOLID。
你function會希望功能專一,路由當然也會希望這樣,網頁系統的路由請你當function name+parameter這樣寫,因為看網頁系統第一步一定是看路由。
我直接講結論,沒人會照你的情境這樣寫API,用錯方法
一個API就是對到一個struct
不會有人寫一個API還要判斷是哪種struct去做unmarshal的
API功能都已經確定了,怎麼可能會有兩種以上的struct包含在一起?
除了將定義好的struct透過embed的方式不算。
你想做的東西是動態解析,而且場景只適用於你不知道input是什麼,卻要解析成你的struct,json package就是在做這件事
或是你想透過像query的方式處理根據field處理input/output,那就是GraphQL
我有寫過短連接用的API所以我可以理解一個API對應到一個struct
目前的情況是前端傳給我的資料就只有一個object,不像呼叫api就只傳對應的struct,如果是這樣當然好判斷
而在使用websocket的情況下一直都是同一條連線,而且沒有指定要打哪個API這件事情,,我只能自己接收資料去判斷這個object的messageCode要執行哪個函式,感覺是websocket部分我還不夠熟。
以前的做法是使用json接收資料沒錯,所以unmarshal後不管其他資料至少messageCode是可以得到讓我判斷,但現在要求換成protobuffer來傳輸我這邊就卡住了
這連結看起來是可以用,不過限制也很多
https://github.com/gogo/protobuf/blob/master/custom_types.md
而且還要用json在unmarshal,這樣用protobuf的優點就消失了啊XD
我是在想如果已經確定了N種資料類型的話
定義proto file的時候寫embed會不會比較簡單?
因為不知道他用的框架是啥,但我猜他的問題websocket一樣可以用route去做,以gin來說分拆出 path parameter 對對應的command做單一struct的對應,這只是在websocket handler 做個switch case的事。
原生的話應該是比較麻煩一點。
其實我上上一個回覆就是在提醒他該從router著手。
或是像你說的,在定義的時候把這種需求考慮進去,弄成embed的。
比較糟的作法是用泛型/interface{}、或是像上面的動態解析json的方式。
這種通常是後端沒法溝通的時候才會做的事,但以protobuf的正常的使用場景,應該很少機會會去用到這個終極手段才對。