當前位置:
首頁 > 最新 > golang中實現通用http參數與結構體的轉換

golang中實現通用http參數與結構體的轉換

更多騰訊海量技術文章,請關注云加社區:https://cloud.tencent.com/developer

作者:衡陣

最近基於golang 實現一個通用的http的協議代理,把來自http的請求轉換成內部的通信協議。內部協議是基於pb的,所以關鍵就是實現pb和http請求中的參數的轉換。

研究protoc生成的go源碼發現,生成的go的結構體中已經自帶的json的tag,可以很方便的在json和pb之間互轉。

於是想到,可以以一個請求參數來傳json來實現。

var data=

var url="http://test.xx.com/cgi-bin/request?data="+urlencode(data)

http.get(url)

這樣在服務端先拿到data的數據,直接用json庫就可以轉成相關的結構體。

這樣實現雖然簡單,但並不直觀。對用戶來說,更習慣用。

var url="http://test.xx.com/cgi-bin/request?name=hello"

這種形式來請求。由於其他語言習慣把請求參數存在一個map中,於是想golang是不是也可以這樣處理。於是問題變成一個map[string]string和json的轉換的故事。搜下網上發現有人提出類似的問題,還是playgroud上的一個練習。代碼如下:

這個代碼實現了簡單的map到struct的轉換,但要求類型強一致。所以需要實現弱類型的轉換。後來發現,github上已經有一個開源的實現。

https://github.com/mitchellh/mapstructure 通過很簡單的代碼就可以實現我們想要的功能

到了這裡,大部分場景都可以實現了。但有些請求是有消息嵌套的,雖然mapstructure是支持嵌套轉換的,但我們的請求參數只是一層的map[string]string。

這種情況mapstructure無能為力了。看下mapstructure的源碼,邏輯比較簡單,既然你不支持,就改到你支持。我們定義如果有結構體嵌套,二級參數要是一個json字元串。在處理結構提的地方,如果發現傳入的是個字元串,就嘗試用json去處理一下,然後再走後面的邏輯。

在slice的地方也同樣處理

這樣處理完了之後試了一下,果然處理嵌套的結構體了。但是在實際使用的時候發現,有人竟然在pb中定義普通的字元串為bytes,這樣在生成的go代碼中就是[]byte類型。這種情況很不巧也會走到decodeSlice的邏輯,而我們並沒有考慮兼容。事實上mapstructure這個框架就沒有考慮這種情形。按json定義的標準,[]byte類型要以base64編碼,我們也遵循這種規範。於是加上這個代碼:

至此,這個轉換基本完美。但是發現一使用,發現還是有坑存在,對應proto文件中定義的帶下劃線的欄位,生成的struct成員代碼是駝峰型的。標準庫中的json可以通過反射拿到tag中的原始名稱正常的輸出。但我們用mapstructure默認是以欄位名來解析的。

本來以為要自己處理一下,在修改一下mapstructure的源碼,然而閱讀代碼的時候發現,mapstructure支持指定要處理的tag。並且tag處理邏輯是兼容pb生成的json tag的。我們只要在解析時指定一下tag即可。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 雲加社區 的精彩文章:

TAG:雲加社區 |